Automatic installer.php lang files by installer_builder (20070726)
[moodle-linuxchix.git] / question / type / datasetdependent / abstractqtype.php
blob8e2bdd9db2ac81f456ee65a62f375e69f545d4ee
1 <?php // $Id$
3 ///////////////////////////////////////////////////////////////
4 /// ABSTRACT SUPERCLASS FOR QUSTION TYPES THAT USE DATASETS ///
5 ///////////////////////////////////////////////////////////////
6 /**
7 * @package questionbank
8 * @subpackage questiontypes
9 */
11 require_once($CFG->libdir.'/filelib.php');
13 define("LITERAL", "1");
14 define("FILE", "2");
15 define("LINK", "3");
17 class question_dataset_dependent_questiontype extends default_questiontype {
19 var $virtualqtype = false;
21 function name() {
22 return 'datasetdependent';
25 function save_question_options($question) {
26 // Default does nothing...
27 return true;
30 function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
31 // Find out how many datasets are available
32 global $CFG;
33 if(!$maxnumber = (int)get_field_sql(
34 "SELECT MIN(a.itemcount)
35 FROM {$CFG->prefix}question_dataset_definitions a,
36 {$CFG->prefix}question_datasets b
37 WHERE b.question = $question->id
38 AND a.id = b.datasetdefinition")) {
39 error("Couldn't get the specified dataset for a calculated " .
40 "question! (question: {$question->id}");
43 // Choose a random dataset
44 $state->options->datasetitem = rand(1, $maxnumber);
45 $state->options->dataset =
46 $this->pick_question_dataset($question,$state->options->datasetitem);
47 $state->responses = array('' => '');
48 return true;
51 function restore_session_and_responses(&$question, &$state) {
52 if (!ereg('^dataset([0-9]+)[^-]*-(.*)$',
53 $state->responses[''], $regs)) {
54 notify ("Wrongly formatted raw response answer " .
55 "{$state->responses['']}! Could not restore session for " .
56 " question #{$question->id}.");
57 $state->options->datasetitem = 1;
58 $state->options->dataset = array();
59 $state->responses = array('' => '');
60 return false;
63 // Restore the chosen dataset
64 $state->options->datasetitem = $regs[1];
65 $state->options->dataset =
66 $this->pick_question_dataset($question,$state->options->datasetitem);
67 $state->responses = array('' => $regs[2]);
68 return true;
71 function save_session_and_responses(&$question, &$state) {
72 $responses = 'dataset'.$state->options->datasetitem.'-'.
73 $state->responses[''];
75 // Set the legacy answer field
76 if (!set_field('question_states', 'answer', $responses, 'id',
77 $state->id)) {
78 return false;
80 return true;
84 function substitute_variables($str, $dataset) {
85 foreach ($dataset as $name => $value) {
86 $str = str_replace('{'.$name.'}', $value, $str);
88 return $str;
91 function uses_quizfile($question, $relativefilepath) {
92 // Check whether the specified file is available by any
93 // dataset item on this question...
94 global $CFG;
95 if (get_record_sql(" SELECT *
96 FROM {$CFG->prefix}question_dataset_items i,
97 {$CFG->prefix}question_dataset_definitions d,
98 {$CFG->prefix}question_datasets q
99 WHERE i.value = '$relativefilepath'
100 AND d.id = i.definition AND d.type = 2
101 AND d.id = q.datasetdefinition
102 AND q.question = $question->id ")) {
104 return true;
105 } else {
106 // Make the check of the parent:
107 return parent::uses_quizfile($question, $relativefilepath);
111 function finished_edit_wizard(&$form) {
112 return isset($form->backtoquiz);
115 // This gets called by editquestion.php after the standard question is saved
116 function print_next_wizard_page(&$question, &$form, $course) {
117 global $CFG, $USER, $SESSION, $COURSE;
119 // Catch invalid navigation & reloads
120 if (empty($question->id) && empty($SESSION->datasetdependent)) {
121 redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired.', 3);
124 // See where we're coming from
125 switch($form->wizardpage) {
126 case 'question':
127 require("$CFG->dirroot/question/type/datasetdependent/datasetdefinitions.php");
128 break;
129 case 'datasetdefinitions':
130 case 'datasetitems':
131 require("$CFG->dirroot/question/type/datasetdependent/datasetitems.php");
132 break;
133 default:
134 error('Incorrect or no wizard page specified!');
135 break;
139 // This gets called by question2.php after the standard question is saved
140 function &next_wizard_form($submiturl, $question, $wizardnow){
141 global $CFG, $SESSION, $COURSE;
143 // Catch invalid navigation & reloads
144 if (empty($question->id) && empty($SESSION->datasetdependent)) {
145 redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired. Cannot get next wizard form.', 3);
147 if (empty($question->id)){
148 $question =& $SESSION->datasetdependent->questionform;
151 // See where we're coming from
152 switch($wizardnow) {
153 case 'datasetdefinitions':
154 require("$CFG->dirroot/question/type/datasetdependent/datasetdefinitions_form.php");
155 $mform =& new question_dataset_dependent_definitions_form("$submiturl?wizardnow=datasetdefinitions", $question);
156 break;
157 case 'datasetitems':
158 require("$CFG->dirroot/question/type/datasetdependent/datasetitems_form.php");
159 $regenerate = optional_param('forceregeneration', 0, PARAM_BOOL);
160 $mform =& new question_dataset_dependent_items_form("$submiturl?wizardnow=datasetitems", $question, $regenerate);
161 break;
162 default:
163 error('Incorrect or no wizard page specified!');
164 break;
167 return $mform;
171 * This method should be overriden if you want to include a special heading or some other
172 * html on a question editing page besides the question editing form.
174 * @param question_edit_form $mform a child of question_edit_form
175 * @param object $question
176 * @param string $wizardnow is '' for first page.
178 function display_question_editing_page(&$mform, $question, $wizardnow){
179 switch ($wizardnow){
180 case '':
181 //on first page default display is fine
182 parent::display_question_editing_page($mform, $question, $wizardnow);
183 return;
184 break;
185 case 'datasetdefinitions':
186 print_heading_with_help(get_string("choosedatasetproperties", "quiz"), "questiondatasets", "quiz");
187 break;
188 case 'datasetitems':
189 print_heading_with_help(get_string("editdatasets", "quiz"), 'questiondatasets', "quiz");
190 break;
194 $mform->display();
199 * This method prepare the $datasets in a format similar to dadatesetdefinitions_form.php
200 * so that they can be saved
201 * using the function save_dataset_definitions($form)
202 * when creating a new calculated question or
203 * whenediting an already existing calculated question
204 * or by function save_as_new_dataset_definitions($form, $initialid)
205 * when saving as new an already existing calculated question
207 * @param object $form
208 * @param int $questionfromid default = '0'
210 function preparedatasets(&$form , $questionfromid='0'){
211 // the dataset names present in the edit_question_form and edit_calculated_form are retrieved
212 $possibledatasets = $this->find_dataset_names($form->questiontext);
213 $mandatorydatasets = array();
214 foreach ($form->answers as $answer) {
215 $mandatorydatasets += $this->find_dataset_names($answer);
217 // if there are identical datasetdefs already saved in the original question.
218 // either when editing a question or saving as new
219 // they are retrieved using $questionfromid
220 if ($questionfromid!='0'){
221 $form->id = $questionfromid ;
223 $datasets = array();
224 $key = 0 ;
225 // always prepare the mandatorydatasets present in the answers
226 // the $options are not used here
227 foreach ($mandatorydatasets as $datasetname) {
228 if (!isset($datasets[$datasetname])) {
229 list($options, $selected) =
230 $this->dataset_options($form, $datasetname);
231 $datasets[$datasetname]='';
232 $form->dataset[$key]=$selected ;
233 $key++;
236 // do not prepare possibledatasets when creating a question
237 // they will defined and stored with datasetdefinitions_form.php
238 // the $options are not used here
239 if ($questionfromid!='0'){
241 foreach ($possibledatasets as $datasetname) {
242 if (!isset($datasets[$datasetname])) {
243 list($options, $selected) =
244 $this->dataset_options($form, $datasetname,false);
245 $datasets[$datasetname]='';
246 $form->dataset[$key]=$selected ;
247 $key++;
251 return $datasets ;
254 * this version save the available data at the different steps of the question editing process
255 * without using global $SESSION as storage between steps
256 * at the first step $wizardnow = 'question'
257 * when creating a new question
258 * when modifying a question
259 * when copying as a new question
260 * the general parameters and answers are saved using parent::save_question
261 * then the datasets are prepared and saved
262 * at the second step $wizardnow = 'datasetdefinitions'
263 * the datadefs final type are defined as private, category or not a datadef
264 * at the third step $wizardnow = 'datasetitems'
265 * the datadefs parameters and the data items are created or defined
267 * @param object question
268 * @param object $form
269 * @param int $course
270 * @param PARAM_ALPHA $wizardnow should be added as we are coming from question2.php
272 function save_question($question, $form, $course) {
273 $wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
274 $id = optional_param('id', 0, PARAM_INT); // question id
275 // in case 'question'
276 // for a new question $form->id is empty
277 // when saving as new question
278 // $question->id = 0, $form is $data from question2.php
279 // and $data->makecopy is defined as $data->id is the initial question id
280 // edit case. If it is a new question we don't necessarily need to
281 // return a valid question object
283 // See where we're coming from
284 switch($wizardnow) {
285 case '' :
286 case 'question': // coming from the first page, creating the second
287 if (empty($form->id)) { // for a new question $form->id is empty
288 $question = parent::save_question($question, $form, $course);
289 //prepare the datasets using default $questionfromid
290 $this->preparedatasets($form);
291 $form->id = $question->id;
292 $this->save_dataset_definitions($form);
293 } else if (!empty($form->makecopy)){
294 $questionfromid = $form->id ;
295 $question = parent::save_question($question, $form, $course);
296 //prepare the datasets
297 $this->preparedatasets($form,$questionfromid);
298 $form->id = $question->id;
299 $this->save_as_new_dataset_definitions($form,$questionfromid );
300 } else {// editing a question
301 $question = parent::save_question($question, $form, $course);
302 //prepare the datasets
303 $this->preparedatasets($form,$question->id);
304 $form->id = $question->id;
305 $this->save_dataset_definitions($form);
307 break;
308 case 'datasetdefinitions':
309 $this->save_dataset_definitions($form);
310 break;
311 case 'datasetitems':
312 $this->save_dataset_items($question, $form);
313 break;
314 default:
315 error('Incorrect or no wizard page specified!');
316 break;
318 return $question;
321 function save_dataset_items($question, $fromform){
322 //overridden in child classes
325 function get_dataset_definitions($questionid, $newdatasets) {
326 //get the existing datasets for this question
327 $datasetdefs = array();
328 if (!empty($questionid)) {
329 global $CFG;
330 $sql = "SELECT i.*
331 FROM {$CFG->prefix}question_datasets d,
332 {$CFG->prefix}question_dataset_definitions i
333 WHERE d.question = '$questionid'
334 AND d.datasetdefinition = i.id
336 if ($records = get_records_sql($sql)) {
337 foreach ($records as $r) {
338 $datasetdefs["$r->type-$r->category-$r->name"] = $r;
343 foreach ($newdatasets as $dataset) {
344 if (!$dataset) {
345 continue; // The no dataset case...
348 if (!isset($datasetdefs[$dataset])) {
349 //make new datasetdef
350 list($type, $category, $name) = explode('-', $dataset, 3);
351 $datasetdef = new stdClass;
352 $datasetdef->type = $type;
353 $datasetdef->name = $name;
354 $datasetdef->category = $category;
355 $datasetdef->itemcount = 0;
356 $datasetdef->options = 'uniform:1.0:10.0:1';
357 $datasetdefs[$dataset] = clone($datasetdef);
360 return $datasetdefs;
363 function save_dataset_definitions($form) {
364 // Save datasets
365 $datasetdefinitions = $this->get_dataset_definitions($form->id, $form->dataset);
366 $tmpdatasets = array_flip($form->dataset);
367 $defids = array_keys($datasetdefinitions);
368 foreach ($defids as $defid) {
369 $datasetdef = &$datasetdefinitions[$defid];
370 if (isset($datasetdef->id)) {
371 if (!isset($tmpdatasets[$defid])) {
372 // This dataset is not used any more, delete it
373 delete_records('question_datasets',
374 'question', $form->id,
375 'datasetdefinition', $datasetdef->id);
376 if ($datasetdef->category == 0) { // Question local dataset
377 delete_records('question_dataset_definitions',
378 'id', $datasetdef->id);
379 delete_records('question_dataset_items',
380 'definition', $datasetdef->id);
383 // This has already been saved or just got deleted
384 unset($datasetdefinitions[$defid]);
385 continue;
388 if (!$datasetdef->id = insert_record(
389 'question_dataset_definitions', $datasetdef)) {
390 error("Unable to create dataset $defid");
393 if (0 != $datasetdef->category) {
394 // We need to look for already existing
395 // datasets in the category.
396 // By first creating the datasetdefinition above we
397 // can manage to automatically take care of
398 // some possible realtime concurrence
399 if ($olderdatasetdefs = get_records_select(
400 'question_dataset_definitions',
401 "type = '$datasetdef->type'
402 AND name = '$datasetdef->name'
403 AND category = '$datasetdef->category'
404 AND id < $datasetdef->id
405 ORDER BY id DESC")) {
407 while ($olderdatasetdef = array_shift($olderdatasetdefs)) {
408 delete_records('question_dataset_definitions',
409 'id', $datasetdef->id);
410 $datasetdef = $olderdatasetdef;
415 // Create relation to this dataset:
416 $questiondataset = new stdClass;
417 $questiondataset->question = $form->id;
418 $questiondataset->datasetdefinition = $datasetdef->id;
419 if (!insert_record('question_datasets',
420 $questiondataset)) {
421 error("Unable to create relation to dataset $name");
423 unset($datasetdefinitions[$defid]);
426 // Remove local obsolete datasets as well as relations
427 // to datasets in other categories:
428 if (!empty($datasetdefinitions)) {
429 foreach ($datasetdefinitions as $def) {
430 delete_records('question_datasets',
431 'question', $form->id,
432 'datasetdefinition', $def->id);
434 if ($def->category == 0) { // Question local dataset
435 delete_records('question_dataset_definitions', 'id', $def->id);
436 delete_records('question_dataset_items',
437 'definition', $def->id);
442 /** This function create a copy of the datasets ( definition and dataitems)
443 * from the preceding question if they remain in the new question
444 * otherwise its create the datasets that have been added as in the
445 * save_dataset_definitions()
447 function save_as_new_dataset_definitions($form, $initialid) {
448 global $CFG ;
449 // Get the datasets from the intial question
450 $datasetdefinitions = $this->get_dataset_definitions($initialid, $form->dataset);
451 // $tmpdatasets contains those of the new question
452 $tmpdatasets = array_flip($form->dataset);
453 $defids = array_keys($datasetdefinitions);// new datasets
454 foreach ($defids as $defid) {
455 $datasetdef = &$datasetdefinitions[$defid];
456 if (isset($datasetdef->id)) {
457 // This dataset exist in the initial question
458 if (!isset($tmpdatasets[$defid])) {
459 // do not exist in the new question so ignore
460 unset($datasetdefinitions[$defid]);
461 continue;
463 // create a copy but not for category one
464 if (0 == $datasetdef->category) {
465 $olddatasetid = $datasetdef->id ;
466 $olditemcount = $datasetdef->itemcount ;
467 $datasetdef->itemcount =0;
468 if (!$datasetdef->id = insert_record(
469 'question_dataset_definitions', $datasetdef)) {
470 error("Unable to create dataset $defid");
472 //copy the dataitems
473 $olditems = get_records_sql( // Use number as key!!
474 " SELECT itemnumber, value
475 FROM {$CFG->prefix}question_dataset_items
476 WHERE definition = $olddatasetid ");
477 if (count($olditems) > 0 ) {
478 $itemcount = 0;
479 foreach($olditems as $item ){
480 $item->definition = $datasetdef->id;
481 if (!insert_record('question_dataset_items', $item)) {
482 error("Unable to insert dataset item $item->itemnumber with $item->value for $datasetdef->name");
484 $itemcount++;
486 //update item count
487 $datasetdef->itemcount =$itemcount;
488 update_record('question_dataset_definitions', $datasetdef);
489 } // end of copy the dataitems
490 }// end of copy the datasetdef
491 // Create relation to the new question with this
492 // copy as new datasetdef from the initial question
493 $questiondataset = new stdClass;
494 $questiondataset->question = $form->id;
495 $questiondataset->datasetdefinition = $datasetdef->id;
496 if (!insert_record('question_datasets',
497 $questiondataset)) {
498 error("Unable to create relation to dataset $name");
500 unset($datasetdefinitions[$defid]);
501 continue;
502 }// end of datasetdefs from the initial question
503 // really new one code similar to save_dataset_definitions()
504 if (!$datasetdef->id = insert_record(
505 'question_dataset_definitions', $datasetdef)) {
506 error("Unable to create dataset $defid");
509 if (0 != $datasetdef->category) {
510 // We need to look for already existing
511 // datasets in the category.
512 // By first creating the datasetdefinition above we
513 // can manage to automatically take care of
514 // some possible realtime concurrence
515 if ($olderdatasetdefs = get_records_select(
516 'question_dataset_definitions',
517 "type = '$datasetdef->type'
518 AND name = '$datasetdef->name'
519 AND category = '$datasetdef->category'
520 AND id < $datasetdef->id
521 ORDER BY id DESC")) {
523 while ($olderdatasetdef = array_shift($olderdatasetdefs)) {
524 delete_records('question_dataset_definitions',
525 'id', $datasetdef->id);
526 $datasetdef = $olderdatasetdef;
531 // Create relation to this dataset:
532 $questiondataset = new stdClass;
533 $questiondataset->question = $form->id;
534 $questiondataset->datasetdefinition = $datasetdef->id;
535 if (!insert_record('question_datasets',
536 $questiondataset)) {
537 error("Unable to create relation to dataset $name");
539 unset($datasetdefinitions[$defid]);
542 // Remove local obsolete datasets as well as relations
543 // to datasets in other categories:
544 if (!empty($datasetdefinitions)) {
545 foreach ($datasetdefinitions as $def) {
546 delete_records('question_datasets',
547 'question', $form->id,
548 'datasetdefinition', $def->id);
550 if ($def->category == 0) { // Question local dataset
551 delete_records('question_dataset_definitions', 'id', $def->id);
552 delete_records('question_dataset_items',
553 'definition', $def->id);
562 function save_question($question, &$form, $course) {
563 // For dataset dependent questions a wizard is used for editing
564 // questions. Therefore saving the question is delayed until
565 // we're through with the whole wizard.
566 global $SESSION;
567 $this->validate_form($form);
569 // See where we're coming from
570 switch($form->wizardpage) {
571 case 'question':
572 unset($SESSION->datasetdependent); // delete any remaining data
573 // from previous wizards
574 if (empty($form->id)) {
575 $SESSION->datasetdependent->question = $form;
576 $question = $this->create_runtime_question($question, $form);
577 } else {
578 $question = parent::save_question($question, $form, $course);
580 break;
581 case 'datasetdefinitions':
582 $SESSION->datasetdependent->datasetdefinitions = $form;
583 if (empty($form->id)) {
584 $question = $this->create_runtime_question($question, $SESSION->datasetdependent->question);
585 } else {
586 $this->save_dataset_definitions($form);
587 $this->get_question_options($question);
588 //unset($SESSION->datasetdependent->datasetdefinitions);
590 //$this->get_question_options($question);
591 break;
592 case 'datasets':
593 if (!empty($form->addbutton) && isset($SESSION->datasetdependent->question)) {
594 echo "saving";
595 $question = parent::save_question($question, $SESSION->datasetdependent->question, $course);
596 $SESSION->datasetdependent->datasetdefinitions->id = $question->id;
597 $this->save_dataset_definitions($SESSION->datasetdependent->datasetdefinitions);
598 //$this->get_dataset_definitions($question);
599 unset($SESSION->datasetdependent);
601 dump($question);
602 if (empty($question->id)) {
603 $question = $this->create_runtime_question($question, $SESSION->datasetdependent->question);
604 } else {
605 $this->get_question_options($question);
608 break;
609 default:
610 error('Incorrect or no wizard page specified!');
611 break;
613 return $question;
620 /// Dataset functionality
621 function pick_question_dataset($question, $datasetitem) {
622 // Select a dataset in the following format:
623 // An array indexed by the variable names (d.name) pointing to the value
624 // to be substituted
625 global $CFG;
626 if (!$dataset = get_records_sql(
627 "SELECT d.name, i.value
628 FROM {$CFG->prefix}question_dataset_definitions d,
629 {$CFG->prefix}question_dataset_items i,
630 {$CFG->prefix}question_datasets q
631 WHERE q.question = $question->id
632 AND q.datasetdefinition = d.id
633 AND d.id = i.definition
634 AND i.itemnumber = $datasetitem")) {
635 error("Couldn't get the specified dataset for a dataset dependent " .
636 "question! (question: {$question->id}, " .
637 "datasetitem: {$datasetitem})");
639 array_walk($dataset, create_function('&$val', '$val = $val->value;'));
640 return $dataset;
643 function create_virtual_qtype() {
644 error("No virtual question type for question type ".$this->name());
647 function get_virtual_qtype() {
648 if (!$this->virtualqtype) {
649 $this->virtualqtype = $this->create_virtual_qtype();
651 return $this->virtualqtype;
654 function comment_header($question) {
655 // Used by datasetitems.php
656 // Default returns nothing and thus takes away the column
657 return '';
660 function comment_on_datasetitems($question, $data, $number) {
661 // Used by datasetitems.php
662 // Default returns nothing
663 return '';
666 function supports_dataset_item_generation() {
667 // Used by datasetitems.php
668 // Default does not support any item generation
669 return false;
672 function custom_generator_tools($datasetdef) {
673 // Used by datasetitems.php
674 // If there is no generation support,
675 // there cannot possibly be any custom tools either
676 return '';
679 function generate_dataset_item($options) {
680 // Used by datasetitems.php
681 // By default nothing is generated
682 return '';
685 function update_dataset_options($datasetdefs, $form) {
686 // Used by datasetitems.php
687 // Returns the updated datasets
688 // By default the dataset options cannot be updated
689 return $datasetdefs;
692 function dataset_options($form, $name,$prefix='',$langfile='quiz') {
694 // First options - it is not a dataset...
695 $options['0'] = get_string($prefix.'nodataset', $langfile);
697 // Construct question local options
698 global $CFG;
699 $currentdatasetdef = get_record_sql(
700 "SELECT a.*
701 FROM {$CFG->prefix}question_dataset_definitions a,
702 {$CFG->prefix}question_datasets b
703 WHERE a.id = b.datasetdefinition
704 AND b.question = '$form->id'
705 AND a.name = '$name'")
706 or $currentdatasetdef->type = '0';
707 foreach (array( LITERAL, FILE, LINK) as $type) {
708 $key = "$type-0-$name";
709 if ($currentdatasetdef->type == $type
710 and $currentdatasetdef->category == 0) {
711 $options[$key] = get_string($prefix."keptlocal$type", $langfile);
712 } else {
713 $options[$key] = get_string($prefix."newlocal$type", $langfile);
717 // Construct question category options
718 $categorydatasetdefs = get_records_sql(
719 "SELECT a.type, a.id
720 FROM {$CFG->prefix}question_dataset_definitions a,
721 {$CFG->prefix}question_datasets b
722 WHERE a.id = b.datasetdefinition
723 AND a.category = '$form->category'
724 AND a.name = '$name'");
725 foreach(array( LITERAL, FILE, LINK) as $type) {
726 $key = "$type-$form->category-$name";
727 if (isset($categorydatasetdefs[$type])
728 and $categorydef = $categorydatasetdefs[$type]) {
729 if ($currentdatasetdef->type == $type
730 and $currentdatasetdef->id == $categorydef->id) {
731 $options[$key] = get_string($prefix."keptcategory$type", $langfile);
732 } else {
733 $options[$key] = get_string($prefix."existingcategory$type", $langfile);
735 } else {
736 $options[$key] = get_string($prefix."newcategory$type", $langfile);
740 // All done!
741 return array($options, $currentdatasetdef->type
742 ? "$currentdatasetdef->type-$currentdatasetdef->category-$name"
743 : '');
746 function find_dataset_names($text) {
747 /// Returns the possible dataset names found in the text as an array
748 /// The array has the dataset name for both key and value
749 $datasetnames = array();
750 while (ereg('\\{([[:alpha:]][^>} <{"\']*)\\}', $text, $regs)) {
751 $datasetnames[$regs[1]] = $regs[1];
752 $text = str_replace($regs[0], '', $text);
754 return $datasetnames;
757 function create_virtual_nameprefix($nameprefix, $datasetinput) {
758 if (!ereg('([0-9]+)' . $this->name() . '$', $nameprefix, $regs)) {
759 error("Wrongly formatted nameprefix $nameprefix");
761 $virtualqtype = $this->get_virtual_qtype();
762 return $nameprefix . $regs[1] . $virtualqtype->name();
766 //// END OF CLASS ////