Index: questiontype.php =================================================================== RCS file: /cvsroot/moodle/moodle/question/type/calculated/questiontype.php,v retrieving revision 1.94 diff -u -r1.94 questiontype.php --- questiontype.php 19 Aug 2010 00:19:49 -0000 1.94 +++ questiontype.php 24 Aug 2010 15:55:48 -0000 @@ -660,6 +660,8 @@ // return a valid question object // See where we're coming from + // echo "

wizardnow $wizardnow

"; + // exit; switch($wizardnow) { case '' : case 'question': // coming from the first page, creating the second @@ -1564,6 +1566,41 @@ return $datasetdefs; } + /** type this function test if the data of the first datasetdef is identical to + ** the data of the second so a question could use the second when moving from the + ** current category to movetocategory + ** same name, definition, moving item count values identical with the values in the moving category + */ + function is_current_categorydataset_can_use_moveto_categorydataset($currentcategorydatasetdef ,$movetocategorycategorydatasetdef){ + /* if ($currentcategorydatasetdef->name != $movetocategorycategorydatasetdef->name) { + // echo "

return false name

"; + + return false ; + }*/ + if (strcmp($currentcategorydatasetdef->options, $movetocategorycategorydatasetdef->options) != 0 ) { + // echo "

return false definition

"; + return false ; + } + if ($currentcategorydatasetdef->itemcount != $movetocategorycategorydatasetdef->itemcount) { + // echo "

return false itemcount

"; + return false ; + } + // compare definition + // get dataitems + $currentitems = $this->get_database_dataset_items($currentcategorydatasetdef->id); + $movetoitems = $this->get_database_dataset_items($movetocategorycategorydatasetdef->id); + $tolerance = (float) ("1.0e-".ini_get('precision')); + // echo "

currentitems

";print_r($currentitems);echo "

"; + // echo "

movetoitems

";print_r($movetoitems);echo "

"; + foreach($currentitems as $i => $currentitem){ + if(!($currentitem->value - $tolerance < $movetoitems[$i]->value && $movetoitems[$i]->value < $currentitem->value + $tolerance )){ + // echo "

return false toleranc $tolerance ".$currentitem->value." XX ".$movetoitems[$i]->value."

"; + return false ; + } + } + return true ; + } + function save_dataset_definitions($form) { global $DB; // save synchronize @@ -1814,6 +1851,210 @@ ? "$currentdatasetdef->type-$currentdatasetdef->category-$name" : ''); } + function move_category_datasets($question){ + global $CFG , $DB ; + $regs= array(); + if (empty($question->id)) { + return true ; + } + // if no category datasets return + $sql = "SELECT i.* + FROM {question_datasets} d, + {question_dataset_definitions} i + WHERE d.question = ? + AND d.datasetdefinition = i.id + AND i.category != 0 + "; + if (!$datasetdefs = $DB->get_records_sql($sql, array($question->id))) { + return true ; + } + $this->get_question_options($question); + $datasetnamechanged = false ; + foreach ($datasetdefs as $def) { + $todo = ''; + $datasetnamechanged = false ; + $postfix = '' ; + $initialname = $def->name ; + $testdef = clone($def) ; + + // first check is the dataset category is the same as the question category + if ($def->category != $question->category ){ + // something to do + // first see if we can use an already existing category + // search for an already existing dataset category with the same name + // and identical dataset values + // if def->name is already in __n format there could be lower index that are identical + // get the datanames already in the movetocategory + if( $allmovetocategorydatasetdefs = $DB->get_records_sql( + "SELECT * FROM {question_dataset_definitions} WHERE category = ? ", array($question->category))) + { + // so there are alreaday some dataset + foreach($allmovetocategorydatasetdefs as $movetodatasetdef){ + // is there one identical dataset with same name ? + if($testdef->name == $movetodatasetdef->name && + $this->is_current_categorydataset_can_use_moveto_categorydataset($testdef ,$movetodatasetdef)){ + + // so use it + $dataset = $DB->get_record('question_datasets', array('question' => $question->id, 'datasetdefinition'=> $def->id)); + $dataset->datasetdefinition = $movetodatasetdef->id; + if ( ! $DB->update_record('question_datasets',$dataset)){ + // todo error message or return false no more in 2.0 + } + $todo = 'done'; + break ; + } + // so def->name is not in movetocategory + // However if def->name is define as xxx__n , we should test lower n values. + // possible case is when the question is move back in its original category + // and in the original move __n was appended for some reasons + $regs = null ; + if(preg_match('~__([1-9][0-9]*)$~',$def->name , $regs)){ + $postfix = $regs[0]; + $postfixindex = $regs[1] ; + $initialname = substr($def->name,0,strlen($def->name)-strlen($regs[0])) ; + // $i < $postfixindex as $postfixindex has already been tested as $def->name + for ($i = 0 ; $i < $postfixindex; $i++){ + if ($i == 0 ) { + $testdef->name = $initialname ; + }else { + $testdef->name = $initialname."__".$i; + } + + foreach($allmovetocategorydatasetdefs as $movetodatasetdef){ + + if($testdef->name == $movetodatasetdef->name && + $this->is_current_categorydataset_can_use_moveto_categorydataset($testdef ,$movetodatasetdef)){ + + // so use it + $dataset = $DB->get_record('question_datasets', array('question' => $question->id, 'datasetdefinition'=> $def->id)); + $dataset->datasetdefinition = $movetodatasetdef->id; + if ( ! $DB->update_record('question_datasets',$dataset)){ + // todo error message or return false no more in 2.0 + } + // notify replace the name in the question texts + $todo = 'changenames'; + $datasetnamechanged = true ; + break ; + } + } + } + } + } + } + // if no identical dataset has been foun in the movetocategory + if($todo == ''){; + // there is no identical category dataset with the same name in the moveto category + // so we copy the initial category dataset in the moveto category. + // However there could be a category dataset with the same name but different data + // So we need to check before copy + // echo "

no categorydatasetdef so we can copy postfix $postfix

"; + $i=0 ; + // the "(preg_match('~__([1-9....] has been done so we can use the result + + if($postfix == ''){ + $testdef->name = $def->name ; + $i = 0 ; + }else { + $testdef->name = $initialname."__".($postfixindex+1); + $i = $postfixindex +1 ; + } + // is it already in allnames ? + // is it already in category ? + // search all possible datasetnames in + $alldatasetnames = $this->find_dataset_names($question->questiontext); + foreach ($question->options->answers as $answer) { + $alldatasetnames += $this->find_dataset_names($answer->answer); + } + do { + // not already in question texts and not created in new category since + // last call + if($i == 0){ + if($postfix == ''){ + $testdef->name = $def->name ; + + }else { + $testdef->name = $initialname ; + } + }else { + $testdef->name = $initialname."__".$i; + } + //$testdef->name = $initialname."__".$i; + //echo "

new datadef dataset

";print_r($testdef);echo "

"; + if(($i == 0 || !isset($alldatasetnames[$testdef->name]))&& + ! $DB->get_records_sql( + "SELECT * FROM {question_dataset_definitions} WHERE category = ? AND name = ?", + array($question->category, $testdef->name ))){ + $olddatasetid = $def->id ; + $olditemcount = $def->itemcount ; + $testdef->itemcount =0; + $testdef->category = $question->category ; + $testdef->id = $DB->insert_record('question_dataset_definitions', $testdef); + // echo "

new datadef dataset

";print_r($testdef);echo "

"; + //copy the dataitems + $olditems = $this->get_database_dataset_items($olddatasetid); + if (count($olditems) > 0 ) { + $itemcount = 0; + foreach($olditems as $item ){ + $item->definition = $testdef->id; + $DB->insert_record('question_dataset_items', $item); + $itemcount++; + } + //update item count to olditemcount if + // at least this number of items has been recover from the database + if( $olditemcount <= $itemcount ) { + $testdef->itemcount = $olditemcount; + } else { + $testdef->itemcount = $itemcount ; + } + $DB->update_record('question_dataset_definitions', $testdef); + } // end of copy the dataitems + $dataset = $DB->get_record('question_datasets', array('question' => $question->id, 'datasetdefinition'=> $olddatasetid)); + $dataset->datasetdefinition = $testdef->id; + // echo "

dataset

";print_r($dataset);echo "

"; + if ( ! $DB->update_record('question_datasets',$dataset)){ + // todo error message or return false + } + $todo = 'done'; + } + $i++; + } while ($i < 6 && $todo != 'done'); + } + + if( $def->name != $testdef->name){ + // echo "

todo $todo $testdef->name

"; + $todo = 'changenames'; + $datasetnamechanged = true ; + + } + if( $todo == 'changenames'){ + // change the dataset name in question text and answers + $question->questiontext = str_replace('{'.$def->name.'}', '{'.$testdef->name.'}', $question->questiontext); + foreach ($question->options->answers as $answer) { + $answer->answer = str_replace('{'.$def->name.'}', '{'.$testdef->name.'}', $answer->answer); + } + $datasetnamechanged = true ; + } + // delete if no used by other questions + if( ! $datasets = $DB->get_records('question_datasets', array( 'datasetdefinition'=> $def->id))){ + $DB->delete_records('question_dataset_definitions', array('id' => $def->id)); + $DB->delete_records('question_dataset_items', array('definition' => $def->id)); + } + }// something to do + }//foreach ($datasetdefs as $def) + // echo "

todo $todo $testdef->name

"; + if ($datasetnamechanged){ + $DB->set_field('question', 'questiontext', $question->questiontext ,array('id' => $question->id)); + foreach ($question->options->answers as $answer) { + $DB->set_field('question_answers', 'answer', $answer->answer,array('id' => $answer->id)); + } + // echo "

todo datasetnamechanged $todo $testdef->name

"; + if(isset($question->options->synchronize) && $question->options->synchronize == 2 ){ + $this->addnamecategory($question); + } + } + // exit ; + } + function find_dataset_names($text) { /// Returns the possible dataset names found in the text as an array