芝麻web文件管理V1.00
编辑当前文件:/home2/sdektunc/.trash/cepali/question/type/calculatedsimple/edit_calculatedsimple_form.php
. /** * Defines the editing form for the calculated simplequestion type. * * @package qtype * @subpackage calculatedsimple * @copyright 2007 Jamie Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/type/calculated/edit_calculated_form.php'); /** * Editing form for the calculated simplequestion type. * * @copyright 2007 Jamie Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_calculatedsimple_edit_form extends qtype_calculated_edit_form { /** * Handle to the question type for this question. * * @var question_calculatedsimple_qtype */ public $qtypeobj; public $wildcarddisplay; public $questiondisplay; public $datasetdefs; public $reload = false; public $maxnumber = -1; public $regenerate = true; public $noofitems; public $outsidelimit = false; public $commentanswer = array(); public $answer = array(); public $nonemptyanswer = array(); public $numbererrors = array(); public $formdata = array(); public function __construct($submiturl, $question, $category, $contexts, $formeditable = true) { $this->regenerate = true; $this->question = $question; $this->qtypeobj = question_bank::get_qtype($this->question->qtype); // Get the dataset definitions for this question. // Coming here everytime even when using a NoSubmitButton. // This will only set the values to the actual question database content // which is not what we want, so this should be removed from here. // Get priority to paramdatasets. $this->reload = optional_param('reload', false, PARAM_BOOL); if (!$this->reload) { // Use database data as this is first pass // Question->id == 0 so no stored datasets. if (!empty($question->id)) { $this->datasetdefs = $this->qtypeobj->get_dataset_definitions( $question->id, array()); if (!empty($this->datasetdefs)) { foreach ($this->datasetdefs as $defid => $datasetdef) { // First get the items in case their number does not correspond to itemcount. if (isset($datasetdef->id)) { $this->datasetdefs[$defid]->items = $this->qtypeobj->get_database_dataset_items($datasetdef->id); if ($this->datasetdefs[$defid]->items != '') { $datasetdef->itemcount = count($this->datasetdefs[$defid]->items); } else { $datasetdef->itemcount = 0; } } // Get maxnumber. if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) { $this->maxnumber = $datasetdef->itemcount; } } } $i = 0; foreach ($this->question->options->answers as $answer) { $this->answer[$i] = $answer; $i++; } $this->nonemptyanswer = $this->answer; } $datasettoremove = false; $newdatasetvalues = false; $newdataset = false; } else { // Handle reload to get values from the form-elements // answers, datasetdefs and data_items. In any case the validation // step will warn the user of any error in settings the values. // Verification for the specific dataset values as the other parameters // units, feeedback etc are handled elsewhere. // Handle request buttons : // 'analyzequestion' (Identify the wild cards {x..} present in answers). // 'addbutton' (create new set of datatitems). // 'updatedatasets' is handled automatically on each reload. // The analyzequestion is done every time on reload // to detect any new wild cards so that the current display reflects // the mandatory (i.e. in answers) datasets. // To implement : don't do any changes if the question is used in a quiz. // If new datadef, new properties should erase items. // most of the data. $datasettoremove = false; $newdatasetvalues = false; $newdataset = false; $dummyform = new stdClass(); $mandatorydatasets = array(); // Should not test on adding a new answer. // Should test if there are already olddatasets or if the 'analyzequestion'. // submit button has been clicked. if (optional_param_array('datasetdef', false, PARAM_BOOL) || optional_param('analyzequestion', false, PARAM_BOOL)) { if ($dummyform->answer = optional_param_array('answer', '', PARAM_NOTAGS)) { // There is always at least one answer... $fraction = optional_param_array('fraction', '', PARAM_FLOAT); $tolerance = optional_param_array('tolerance', '', PARAM_LOCALISEDFLOAT); $tolerancetype = optional_param_array('tolerancetype', '', PARAM_FLOAT); $correctanswerlength = optional_param_array('correctanswerlength', '', PARAM_INT); $correctanswerformat = optional_param_array('correctanswerformat', '', PARAM_INT); foreach ($dummyform->answer as $key => $answer) { if (trim($answer) != '') { // Just look for non-empty. $this->answer[$key] = new stdClass(); $this->answer[$key]->answer = $answer; $this->answer[$key]->fraction = $fraction[$key]; $this->answer[$key]->tolerance = $tolerance[$key]; $this->answer[$key]->tolerancetype = $tolerancetype[$key]; $this->answer[$key]->correctanswerlength = $correctanswerlength[$key]; $this->answer[$key]->correctanswerformat = $correctanswerformat[$key]; $this->nonemptyanswer[]= $this->answer[$key]; $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer); } } } $this->datasetdefs = array(); // Rebuild datasetdefs from old values. if ($olddef = optional_param_array('datasetdef', '', PARAM_RAW)) { $calcmin = optional_param_array('calcmin', '', PARAM_LOCALISEDFLOAT); $calclength = optional_param_array('calclength', '', PARAM_INT); $calcmax = optional_param_array('calcmax', '', PARAM_LOCALISEDFLOAT); $oldoptions = optional_param_array('defoptions', '', PARAM_RAW); $newdatasetvalues = false; $sizeofolddef = count($olddef); for ($key = 1; $key <= $sizeofolddef; $key++) { $def = $olddef[$key]; $this->datasetdefs[$def]= new stdClass(); $this->datasetdefs[$def]->type = 1; $this->datasetdefs[$def]->category = 0; $this->datasetdefs[$def]->options = $oldoptions[$key]; $this->datasetdefs[$def]->calcmin = $calcmin[$key]; $this->datasetdefs[$def]->calcmax = $calcmax[$key]; $this->datasetdefs[$def]->calclength = $calclength[$key]; // Then compare with new values. if (preg_match('~^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$~', $this->datasetdefs[$def]->options, $regs)) { if ($this->datasetdefs[$def]->calcmin != $regs[2]|| $this->datasetdefs[$def]->calcmax != $regs[3] || $this->datasetdefs[$def]->calclength != $regs[4]) { $newdatasetvalues = true; } } $this->datasetdefs[$def]->options = "uniform:" . $this->datasetdefs[$def]->calcmin . ":" . $this->datasetdefs[$def]->calcmax . ":" . $this->datasetdefs[$def]->calclength; } } // Detect new datasets. $newdataset = false; foreach ($mandatorydatasets as $datasetname) { if (!isset($this->datasetdefs["1-0-{$datasetname}"])) { $key = "1-0-{$datasetname}"; $this->datasetdefs[$key] = new stdClass(); $this->datasetdefs[$key]->type = 1; $this->datasetdefs[$key]->category = 0; $this->datasetdefs[$key]->name = $datasetname; $this->datasetdefs[$key]->options = "uniform:1.0:10.0:1"; $newdataset = true; } else { $this->datasetdefs["1-0-{$datasetname}"]->name = $datasetname; } } // Remove obsolete datasets. $datasettoremove = false; foreach ($this->datasetdefs as $defkey => $datasetdef) { if (!isset($datasetdef->name)) { $datasettoremove = true; unset($this->datasetdefs[$defkey]); } } } } // Handle reload. // Create items if $newdataset and noofitems > 0 and !$newdatasetvalues. // Eliminate any items if $newdatasetvalues. // Eliminate any items if $datasettoremove, $newdataset, $newdatasetvalues. if ($datasettoremove ||$newdataset ||$newdatasetvalues) { foreach ($this->datasetdefs as $defkey => $datasetdef) { $datasetdef->itemcount = 0; unset($datasetdef->items); } } $maxnumber = -1; if (optional_param('addbutton', false, PARAM_BOOL)) { $maxnumber = optional_param('selectadd', '', PARAM_INT); // FIXME: sloppy coding. foreach ($this->datasetdefs as $defid => $datasetdef) { $datasetdef->itemcount = $maxnumber; unset($datasetdef->items); for ($numberadded = 1; $numberadded <= $maxnumber; $numberadded++) { $datasetitem = new stdClass(); $datasetitem->itemnumber = $numberadded; $datasetitem->id = 0; $datasetitem->value = $this->qtypeobj->generate_dataset_item( $datasetdef->options); $this->datasetdefs[$defid]->items[$numberadded] = $datasetitem; } } $this->maxnumber = $maxnumber; } else { // Handle reload dataset items. if (optional_param_array('definition', '', PARAM_NOTAGS) && !($datasettoremove ||$newdataset ||$newdatasetvalues)) { $i = 1; $fromformdefinition = optional_param_array('definition', '', PARAM_NOTAGS); $fromformnumber = optional_param_array('number', '', PARAM_LOCALISEDFLOAT); $fromformitemid = optional_param_array('itemid', '', PARAM_INT); ksort($fromformdefinition); foreach ($fromformdefinition as $key => $defid) { $addeditem = new stdClass(); $addeditem->id = $fromformitemid[$i]; $addeditem->value = $fromformnumber[$i]; $addeditem->itemnumber = ceil($i / count($this->datasetdefs)); $this->datasetdefs[$defid]->items[$addeditem->itemnumber] = $addeditem; $this->datasetdefs[$defid]->itemcount = $i; $i++; } } if (isset($addeditem->itemnumber) && $this->maxnumber < $addeditem->itemnumber) { $this->maxnumber = $addeditem->itemnumber; if (!empty($this->datasetdefs)) { foreach ($this->datasetdefs as $datasetdef) { $datasetdef->itemcount = $this->maxnumber; } } } } parent::__construct($submiturl, $question, $category, $contexts, $formeditable); } /** * Add question-type specific form fields. * * @param MoodleQuickForm $mform the form being built. */ protected function definition_inner($mform) { $strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer); $label = get_string("sharedwildcards", "qtype_calculated"); $mform->addElement('hidden', 'synchronize', 0); $mform->addElement('hidden', 'initialcategory', 1); $mform->setType('synchronize', PARAM_BOOL); $mform->setType('initialcategory', PARAM_INT); $mform->addElement('hidden', 'reload', 1); $mform->setType('reload', PARAM_INT); $addfieldsname = 'updatequestion value'; $addstring = get_string("updatecategory", "qtype_calculated"); $mform->registerNoSubmitButton($addfieldsname); $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'), question_bank::fraction_options(), 1, 1); $this->add_unit_options($mform, $this); $this->add_unit_fields($mform, $this); $this->add_interactive_settings(); $label = "
" . get_string('wildcardrole', 'qtype_calculatedsimple') . "
"; $mform->addElement('html', "
"); // Explaining the role of datasets so other strings can be shortened. $mform->addElement('html', $label); $mform->addElement('submit', 'analyzequestion', get_string('findwildcards', 'qtype_calculatedsimple')); $mform->registerNoSubmitButton('analyzequestion'); $mform->closeHeaderBefore('analyzequestion'); $this->wizarddisplay = optional_param('analyzequestion', false, PARAM_BOOL); if ($this->maxnumber != -1) { $this->noofitems = $this->maxnumber; } else { $this->noofitems = 0; } if (!empty($this->datasetdefs)) {// So there are some datadefs. // We put them on the page. $key = 0; $mform->addElement('header', 'additemhdr', get_string('wildcardparam', 'qtype_calculatedsimple')); $idx = 1; if (!empty($this->datasetdefs)) {// Unnecessary test. $j = (($this->noofitems) * count($this->datasetdefs))+1;// foreach ($this->datasetdefs as $defkey => $datasetdef) { $mform->addElement('static', "na[{$j}]", get_string('param', 'qtype_calculated', $datasetdef->name)); $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j); $mform->addElement('hidden', "datasetdef[{$idx}]"); $mform->setType("datasetdef[{$idx}]", PARAM_RAW); $mform->addElement('hidden', "defoptions[{$idx}]"); $mform->setType("defoptions[{$idx}]", PARAM_RAW); $idx++; $mform->addElement('static', "divider[{$j}]", '', '
'); $j++; } } // This should be done before the elements are created and stored as $this->formdata. // Fill out all data sets and also the fields for the next item to add. /*Here we do already the values error analysis so that * we could force all wild cards values display if there is an error in values. * as using a , in a number */ $this->numbererrors = array(); if (!empty($this->datasetdefs)) { $j = $this->noofitems * count($this->datasetdefs); for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--) { $data = array(); $numbererrors = ''; $comment = new stdClass(); $comment->stranswers = array(); $comment->outsidelimit = false; $comment->answers = array(); foreach ($this->datasetdefs as $defid => $datasetdef) { if (isset($datasetdef->items[$itemnumber])) { $this->formdata["definition[{$j}]"] = $defid; $this->formdata["itemid[{$j}]"] = $datasetdef->items[$itemnumber]->id; $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value; $this->formdata["number[{$j}]"] = $number = $datasetdef->items[$itemnumber]->value; if (! is_numeric($number)) { $a = new stdClass(); $a->name = '{'.$datasetdef->name.'}'; $a->value = $datasetdef->items[$itemnumber]->value; if (stristr($number, ',')) { $this->numbererrors["number[{$j}]"] = get_string('nocommaallowed', 'qtype_calculated'); $numbererrors .= $this->numbererrors['number['.$j.']']."
"; } else { $this->numbererrors["number[{$j}]"] = get_string('notvalidnumber', 'qtype_calculated', $a); $numbererrors .= $this->numbererrors['number['.$j.']']."
"; } } else if (stristr($number, 'x')) { // Hexa will pass the test. $a = new stdClass(); $a->name = '{'.$datasetdef->name.'}'; $a->value = $datasetdef->items[$itemnumber]->value; $this->numbererrors['number['.$j.']'] = get_string('hexanotallowed', 'qtype_calculated', $a); $numbererrors .= $this->numbererrors['number['.$j.']']."
"; } else if (is_nan($number)) { $a = new stdClass(); $a->name = '{'.$datasetdef->name.'}'; $a->value = $datasetdef->items[$itemnumber]->value; $this->numbererrors["number[{$j}]"] = get_string('notvalidnumber', 'qtype_calculated', $a); $numbererrors .= $this->numbererrors['number['.$j.']']."
"; } } $j--; } if ($this->noofitems != 0) { if (empty($numbererrors)) { if (!isset($this->question->id)) { $this->question->id = 0; } $this->question->questiontext = !empty($this->question->questiontext) ? $this->question->questiontext : ''; $comment = $this->qtypeobj->comment_on_datasetitems( $this->qtypeobj, $this->question->id, $this->question->questiontext, $this->nonemptyanswer, $data, $itemnumber); if ($comment->outsidelimit) { $this->outsidelimit = $comment->outsidelimit; } $totalcomment = ''; foreach ($this->nonemptyanswer as $key => $answer) { $totalcomment .= $comment->stranswers[$key].'
'; } $this->formdata['answercomment['.$itemnumber.']'] = $totalcomment; } } } $this->formdata['selectdelete'] = '1'; $this->formdata['selectadd'] = '1'; $j = $this->noofitems * count($this->datasetdefs)+1; $data = array(); // Data for comment_on_datasetitems later. $idx = 1; foreach ($this->datasetdefs as $defid => $datasetdef) { $this->formdata["datasetdef[{$idx}]"] = $defid; $idx++; } $this->formdata = $this->qtypeobj->custom_generator_set_data( $this->datasetdefs, $this->formdata); } $addoptions = Array(); $addoptions['1'] = '1'; for ($i = 10; $i <= 100; $i += 10) { $addoptions["{$i}"] = "{$i}"; } $showoptions = Array(); $showoptions['1'] = '1'; $showoptions['2'] = '2'; $showoptions['5'] = '5'; for ($i = 10; $i <= 100; $i += 10) { $showoptions["{$i}"] = "{$i}"; } $mform->closeHeaderBefore('additemhdr'); $addgrp = array(); $addgrp[] = $mform->createElement('submit', 'addbutton', get_string('generatenewitemsset', 'qtype_calculatedsimple')); $addgrp[] = $mform->createElement('select', "selectadd", '', $addoptions); $addgrp[] = $mform->createElement('static', "stat", '', get_string('newsetwildcardvalues', 'qtype_calculatedsimple')); $mform->addGroup($addgrp, 'addgrp', '', ' ', false); $mform->registerNoSubmitButton('addbutton'); $mform->closeHeaderBefore('addgrp'); $addgrp1 = array(); $addgrp1[] = $mform->createElement('submit', 'showbutton', get_string('showitems', 'qtype_calculatedsimple')); $addgrp1[] = $mform->createElement('select', "selectshow", '', $showoptions); $addgrp1[] = $mform->createElement('static', "stat", '', get_string('setwildcardvalues', 'qtype_calculatedsimple')); $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false); $mform->registerNoSubmitButton('showbutton'); $mform->closeHeaderBefore('addgrp1'); $mform->addElement('static', "divideradd", '', ''); if ($this->noofitems == 0) { $mform->addElement('static', 'warningnoitems', '', '
' . get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple') . '
'); $mform->closeHeaderBefore('warningnoitems'); } else { $mform->addElement('header', 'additemhdr1', get_string('wildcardvalues', 'qtype_calculatedsimple')); $mform->closeHeaderBefore('additemhdr1'); if (!empty($this->numbererrors) || $this->outsidelimit) { $mform->addElement('static', "alert", '', '
' . get_string('useadvance', 'qtype_calculatedsimple').'
'); } $mform->addElement('submit', 'updatedatasets', get_string('updatewildcardvalues', 'qtype_calculatedsimple')); $mform->registerNoSubmitButton('updatedatasets'); $mform->setAdvanced("updatedatasets", true); // ...--------------------------------------------------------------. $j = $this->noofitems * count($this->datasetdefs); $k = optional_param('selectshow', 1, PARAM_INT); for ($i = $this->noofitems; $i >= 1; $i--) { foreach ($this->datasetdefs as $defkey => $datasetdef) { if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { $mform->addElement('float', "number[{$j}]", get_string( 'wildcard', 'qtype_calculatedsimple', $datasetdef->name)); $mform->setAdvanced("number[{$j}]", true); if (!empty($this->numbererrors['number['.$j.']'])) { $mform->addElement('static', "numbercomment[{$j}]", '', '
' . $this->numbererrors['number['.$j.']'] . '
'); $mform->setAdvanced("numbercomment[{$j}]", true); } } else { $mform->addElement('hidden', "number[{$j}]", ''); $mform->setType("number[{$j}]", PARAM_LOCALISEDFLOAT); // Localisation handling has to be done manually. if (isset($this->formdata["number[{$j}]"])) { $this->formdata["number[{$j}]"] = format_float($this->formdata["number[{$j}]"], -1); } } $mform->addElement('hidden', "itemid[{$j}]"); $mform->setType("itemid[{$j}]", PARAM_INT); $mform->addElement('hidden', "definition[{$j}]"); $mform->setType("definition[{$j}]", PARAM_NOTAGS); $j--; } if (!empty($strquestionlabel) && ($k > 0 || $this->outsidelimit || !empty($this->numbererrors))) { $mform->addElement('static', "answercomment[{$i}]", "
" . get_string('setno', 'qtype_calculatedsimple', $i) . "
" . $strquestionlabel); } if ($k > 0 || $this->outsidelimit || !empty($this->numbererrors)) { $mform->addElement('static', "divider1[{$j}]", '', '
'); } $k--; } } } else { $mform->addElement('static', 'warningnowildcards', '', '
' . get_string('atleastonewildcard', 'qtype_calculatedsimple') . '
'); $mform->closeHeaderBefore('warningnowildcards'); } // ...----------------------------------------------------------------------. // Non standard name for button element needed so not using add_action_buttons. // Hidden elements. $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid'); $mform->setType('courseid', PARAM_INT); $mform->setDefault('courseid', 0); $mform->addElement('hidden', 'cmid'); $mform->setType('cmid', PARAM_INT); $mform->setDefault('cmid', 0); if (!empty($this->question->id)) { if ($this->question->formoptions->cansaveasnew) { $mform->addElement('header', 'additemhdr', get_string('converttocalculated', 'qtype_calculatedsimple')); $mform->closeHeaderBefore('additemhdr'); $mform->addElement('checkbox', 'convert', '', get_string('willconverttocalculated', 'qtype_calculatedsimple')); $mform->setDefault('convert', 0); } } } protected function can_preview() { return empty($this->question->beingcopied) && !empty($this->question->id) && $this->question->formoptions->canedit && $this->noofitems > 0; } public function data_preprocessing($question) { $question = parent::data_preprocessing($question); $question = $this->data_preprocessing_answers($question); $question = $this->data_preprocessing_hints($question); $question = $this->data_preprocessing_units($question); $question = $this->data_preprocessing_unit_options($question); // This is a bit ugly, but it loads all the dataset values. $question = (object)((array)$question + $this->formdata); return $question; } public function qtype() { return 'calculatedsimple'; } public function validation($data, $files) { $errors = parent::validation($data, $files); if (array_key_exists('number', $data)) { $numbers = $data['number']; } else { $numbers = array(); } foreach ($numbers as $key => $number) { if (! is_numeric($number)) { if (stristr($number, ',')) { $errors['number['.$key.']'] = get_string('nocommaallowed', 'qtype_calculated'); } else { $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); } } else if (stristr($number, 'x')) { $a = new stdClass(); $a->name = ''; $a->value = $number; $errors['number['.$key.']'] = get_string('hexanotallowed', 'qtype_calculated', $a); } else if (is_nan($number)) { $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated'); } } if (empty($data['definition'])) { $errors['selectadd'] = get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple'); } return $errors; } }