Finds errors in question slots.

@param string $questiontext The question text
@param array $choices Question choices
@return string|bool Error message or false if no errors
516126
private function validate_slots($questiontext, $choices) {
        $error = 'Please check the Question text: ';
        if (!$questiontext) {
            return get_string('errorquestiontextblank', 'qtype_gapselect');
        }

        $matches = array();
        preg_match_all($this->squarebracketsregex, $questiontext, $matches);
        $slots = $matches[0];

        if (!$slots) {
            return get_string('errornoslots', 'qtype_gapselect');
        }

        $cleanedslots = array();
        foreach ($slots as $slot) {
            // The 2 is for'[[' and 4 is for '[[]]'.
            $cleanedslots[] = substr($slot, 2, (strlen($slot) - 4));
        }
        $slots = $cleanedslots;

        $found = false;
        foreach ($slots as $slot) {
            $found = false;
            foreach ($choices as $key => $choice) {
                if ($slot == $key + 1) {
                    if ($choice['answer'] === '') {
                        return get_string('errorblankchoice', 'qtype_gapselect',
                                html_writer::tag('b', $slot));
                    }
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                return get_string('errormissingchoice', 'qtype_gapselect',
                        html_writer::tag('b', $slot));
            }
        }
        return false;
    }
326326
protected function isValidChoice($choice, array $choices, bool $case)
    {
        if ($this->isAssocChoice($choices)) {
            $choices = \array_keys($choices);
        }

        $fn = ['\strcasecmp', '\strcmp'][(int) $case];

        foreach ($choices as $option) {
            if ($fn($choice, $option) == 0) {
                return true;
            }
        }

        return false;
    }
1065921
public function choose($string, array $choices, $useChoiceKeysAsSelector = true) {
        $this->output->writeLine("<question>$string</question>");

        $choicesMap = [];

        foreach ($choices as $subject => $message) {
            if ($useChoiceKeysAsSelector) {
                $index = $subject;
            } else {
                $index = count($choicesMap) + 1;
            }

            $choicesMap[$index] = [
                'subject' => $subject,
                'message' => $message,
            ];
        }

        foreach ($choicesMap as $index => $choice) {
            $message = array_get($choice, 'message');

            $this->output->writeLineIndented("[<yellow>$index</yellow>] $message");
        }

        $choice = null;

        while (true) {
            $this->output->writeIndented('Choice: ');
            $input = $this->input->readLine();

            if (array_has($choicesMap, $input)) {
                $choice = array_get(array_get($choicesMap, $input), 'subject');
                break;
            }

            if ( ! empty($input)) {
                $this->output->writeLineIndented('<yellow>Invalid choice</yellow>');
            }
        }

        return $choice;
    }
453918
public function choose($question, array $options, $default, $error_message)
	{
		/** @var QuestionHelper $helper */
		$helper = $this->_helperSet->get('question');
		$choice_question = new ChoiceQuestion('<question>' . $question . '</question> ', $options, $default);
		$choice_question->setErrorMessage($error_message);

		return $helper->ask($this->_input, $this->_output, $choice_question);
	}
535467
public function validateMultipleChoice($answer, $choice)
    {
        $answers = explode(',', $answer);

        foreach ($answers as $ans) {
            if (!in_array(trim($ans), $choice)) {
                return false;
            }

            $formatedAnswers[] = trim($ans);
        }

        return $formatedAnswers;
    }
1186486
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;
    }
343965
public function getChoicesAsSeparateEmailUsername(array &$choices)
    {
        $ret = [];
        foreach ($choices as $item) {
            $ret[] = $item->getEmail();
            $ret[] = $item->getUsername();
        }

        return $ret;
    }
357153
final protected function askAndValidate(
        InputInterface $input,
        OutputInterface $output,
        $questionText,
        $default,
        $validator
    ) {
        $questionHelper = $this->getQuestionHelper();

        $question = new Question($questionHelper->getQuestion($questionText, $default), $default);

        $question->setValidator($validator);

        return $questionHelper->ask($input, $output, $question);
    }
68615
public static function getOptionalErrors(array $data, array $errors = [])
    {
        // auth_flag - small
        if (isset($data['auth_flag']) && !UtilityValidator::isSmall($data['auth_flag'])) {
            $errors['auth_flag'] = 'Should be between 0 and 9';
        }

        return $errors;
    }
800448
public function askWithCompletion($question, array $choices, $default = null)
    {
        $helper = $this->getHelperSet()->get('question');

        $question = new Question("<question>$question</question> ", $default);

        $question->setAutocompleterValues($choices);

        return $helper->ask($this->input, $this->output, $question);
    }
1346213
public function getOptionalErrors(array $data, array &$errors = [], $fieldset = null)
    {
        $schema = $this->schema;

        if (!is_null($fieldset)) {
            $schema = $fieldset;
        }

        $fields = $schema->getFields();
        $table = $schema->getName();
        $primary = $schema->getPrimaryFieldName();

        foreach ($fields as $field) {
            $name = $table . '_' . $field['name'];
            //if there is no data
            if (!isset($data[$name])) {
                //no need to validate
                continue;
            }

            if (!isset($field['validation']) || !is_array($field['validation'])) {
                continue;
            }

            foreach ($field['validation'] as $validation) {
                switch (true) {
                    case in_array($validation['method'], ['column_gt', 'column_gte', 'column_lt', 'column_lte'])
                        && !isset($data[$validation['parameters']]):
                        $errors[$name] = cradle('global')
                            ->translate('Column compared against does not exist. Please check schema.');
                        break;
                    case $validation['method'] === 'column_gt'
                        && !($data[$name] > $data[$validation['parameters']]):
                    case $validation['method'] === 'column_gte'
                        && !($data[$name] >= $data[$validation['parameters']]):
                    case $validation['method'] === 'column_lt'
                        && !($data[$name] < $data[$validation['parameters']]):
                    case $validation['method'] === 'column_lte'
                        && !($data[$name] <= $data[$validation['parameters']]):
                    case $validation['method'] === 'empty'
                        && empty($data[$name]):
                    case $validation['method'] === 'number'
                        && !is_numeric($data[$name]):
                    case $validation['method'] === 'float'
                        && !preg_match('/^[-+]?(\d*)?\.\d+$/', $data[$name]):
                    case $validation['method'] === 'price'
                        && !preg_match('/^[-+]?(\d*)?\.\d{2}$/', $data[$name]):
                    case $validation['method'] === 'price'
                        && !is_numeric($data[$name]):
                    case $validation['method'] === 'regexp'
                        && !preg_match($validation['parameters'], $data[$name]):
                    case $validation['method'] === 'gt'
                        && !($data[$name] > $validation['parameters']):
                    case $validation['method'] === 'gte'
                        && !($data[$name] >= $validation['parameters']):
                    case $validation['method'] === 'lt'
                        && !($data[$name] < $validation['parameters']):
                    case $validation['method'] === 'lte'
                        && !($data[$name] <= $validation['parameters']):
                    case $validation['method'] === 'char_gt'
                        && !(strlen($data[$name]) > $validation['parameters']):
                    case $validation['method'] === 'char_gte'
                        && !(strlen($data[$name]) >= $validation['parameters']):
                    case $validation['method'] === 'char_lt'
                        && !(strlen($data[$name]) < $validation['parameters']):
                    case $validation['method'] === 'char_lte'
                        && !(strlen($data[$name]) <= $validation['parameters']):
                    case $validation['method'] === 'word_gt'
                        && !(str_word_count($data[$name]) > $validation['parameters']):
                    case $validation['method'] === 'word_gte'
                        && !(str_word_count($data[$name]) >= $validation['parameters']):
                    case $validation['method'] === 'word_lt'
                        && !(str_word_count($data[$name]) < $validation['parameters']):
                    case $validation['method'] === 'word_lte'
                        && !(str_word_count($data[$name]) <= $validation['parameters']):
                    case $validation['method'] === 'date'
                        && !preg_match('/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/', $data[$name]):
                    case $validation['method'] === 'time'
                        && !preg_match('/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $data[$name]):
                    case $validation['method'] === 'datetime'
                        && !preg_match('/^[0-9]{4}\-[0-9]{2}\-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/', $data[$name]):
                    case $validation['method'] === 'futuredate'
                        && !(strtotime($data[$name]) > strtotime(date('Y-m-d'))):
                    case $validation['method'] === 'pastdate'
                        && !(strtotime($data[$name]) < strtotime(date('Y-m-d'))):
                    case $validation['method'] === 'presentdate'
                        && !(strtotime($data[$name]) == strtotime(date('Y-m-d'))):
                    case $validation['method'] === 'email'
                        && !preg_match('/^(?:(?:(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|\x5c(?=[@,"\[\]'.
                        '\x5c\x00-\x20\x7f-\xff]))(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]'.
                        '\x5c\x00-\x20\x7f-\xff]|\x5c(?=[@,"\[\]\x5c\x00-\x20\x7f-\xff])|\.(?=[^\.])){1,62'.
                        '}(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]\x5c\x00-\x20\x7f-\xff])|'.
                        '[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]{1,2})|"(?:[^"]|(?<=\x5c)"){1,62}")@(?:(?!.{64})'.
                        '(?:[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.?|[a-zA-Z0-9]\.?)+\.(?:xn--[a-zA-Z0-9]'.
                        '+|[a-zA-Z]{2,6})|\[(?:[0-1]?\d?\d|2[0-4]\d|25[0-5])(?:\.(?:[0-1]?\d?\d|2[0-4]\d|25'.
                        '[0-5])){3}\])$/', $data[$name]):
                    case $validation['method'] === 'url'
                        && !preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0'.
                        '-9_-]*(?:.[A-Z0-9][A-Z0-9_-]*)+):?(d+)?\/?/i', $data[$name]):
                    case $validation['method'] === 'hex'
                        && preg_match('/^[0-9a-fA-F]{6}$/', $data[$name]):
                    case $validation['method'] === 'cc'
                        && !preg_match('/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]'.
                        '{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-'.
                        '5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/', $data[$name]):
                        $errors[$name] = $validation['message'];
                        break;
                    case $validation['method'] === 'one':
                        if (!in_array($data[$name], $validation['parameters'])) {
                            $errors[$name] = $validation['message'];
                        }
                        break;
                    case $validation['method'] === 'unique':
                        $search = Service::get('sql')
                            ->getResource()
                            ->search($table)
                            ->addFilter($name . '= %s', $data[$name]);

                        if (isset($data[$primary])) {
                            $search->addFilter($primary . ' != %s', $data[$primary]);
                        }

                        if ($search->getTotal()) {
                            $errors[$name] = $validation['message'];
                        }
                        break;
                }
            }
        }

        return $errors;
    }
1137349
protected function populate_missing_questions($slots) {
        // Address missing question types.
        foreach ($slots as $slot) {
            if ($slot->qtype === null) {
                // If the questiontype is missing change the question type.
                $slot->id = $slot->questionid;
                $slot->category = 0;
                $slot->qtype = 'missingtype';
                $slot->name = get_string('missingquestion', 'quiz');
                $slot->slot = $slot->slot;
                $slot->maxmark = 0;
                $slot->requireprevious = 0;
                $slot->questiontext = ' ';
                $slot->questiontextformat = FORMAT_HTML;
                $slot->length = 1;

            } else if (!\question_bank::qtype_exists($slot->qtype)) {
                $slot->qtype = 'missingtype';
            }
        }

        return $slots;
    }
992354
public function load_choices() {
        global $CFG;

        if (is_array($this->choices)) {
            return true;
        }

        require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php');
        $this->choices = qtype_multichoice::get_numbering_styles();

        return true;
    }
271886
public function validateSolutions(array $question)
    {
        $errors = [];

        // check solution IDs are consistent with proposals IDs
        $proposalIds = array_map(function (array $proposal) {
            return $proposal['id'];
        }, $question['firstSet']);

        $labelIds = array_map(function (array $label) {
            return $label['id'];
        }, $question['secondSet']);

        $maxScore = -1;
        foreach ($question['solutions'] as $index => $solution) {
            if (!in_array($solution['firstId'], $proposalIds)) {
                $errors[] = [
                    'path' => "/solutions[{$index}]",
                    'message' => "id {$solution['firstId']} doesn't match any proposal id",
                ];
            }

            if (!in_array($solution['secondId'], $labelIds)) {
                $errors[] = [
                    'path' => "/solutions[{$index}]",
                    'message' => "id {$solution['secondId']} doesn't match any label id",
                ];
            }

            if ($solution['score'] > $maxScore) {
                $maxScore = $solution['score'];
            }
        }

        // Checks there is a positive score solution
        if ($maxScore <= 0) {
            $errors[] = [
                'path' => '/solutions',
                'message' => 'There is no solution with a positive score',
            ];
        }

        return $errors;
    }
1219473
protected function askOptions(string $description, array $options, int $default, $multiSelect = false)
    {
        $helper   = $this->getHelper('question');
        $question = new ChoiceQuestion(
            $description,
            $options,
            $default
        );
        if ($multiSelect) {
            $question->setMultiselect(true);
        }
        $question->setErrorMessage('Answer is invalid');
        $answer = $helper->ask($this->input, $this->output, $question);

        return $answer;
    }
786038
final protected function askList($question, $items)
    {
        $indent = ($this->indent > 0) ? $this->indent : 0;
        $question = sprintf('%s%s: ', str_repeat(' ', 4 * $indent), $question);

        $question = new ChoiceQuestion($question, $items);
        return $this->getHelper('question')->ask($this->input, $this->output, $question);
    }
833906
private function get_number_of_questions_to_add_choices() {
        $maxrand = 100;
        $randomcount = array();
        for ($i = 1; $i <= min(10, $maxrand); $i++) {
            $randomcount[$i] = $i;
        }
        for ($i = 20; $i <= min(100, $maxrand); $i += 10) {
            $randomcount[$i] = $i;
        }
        return $randomcount;
    }