[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/lesson/ -> format.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * format.php  - Default format class for file imports/exports. Doesn't do
  20   * everything on it's own -- it needs to be extended.
  21   *
  22   * Included by import.ph
  23   *
  24   * @package mod_lesson
  25   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   **/
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * Import files embedded into answer or response
  33   *
  34   * @param string $field nfield name (answer or response)
  35   * @param array $data imported data
  36   * @param object $answer answer object
  37   * @param int $contextid
  38   **/
  39  function lesson_import_question_files($field, $data, $answer, $contextid) {
  40      global $DB;
  41      if (!isset($data['itemid'])) {
  42          return;
  43      }
  44      $text = file_save_draft_area_files($data['itemid'],
  45              $contextid, 'mod_lesson', 'page_' . $field . 's', $answer->id,
  46              array('subdirs' => false, 'maxfiles' => -1, 'maxbytes' => 0),
  47              $answer->$field);
  48  
  49      $DB->set_field("lesson_answers", $field, $text, array("id" => $answer->id));
  50  }
  51  
  52  /**
  53   * Given some question info and some data about the the answers
  54   * this function parses, organises and saves the question
  55   *
  56   * This is only used when IMPORTING questions and is only called
  57   * from format.php
  58   * Lifted from mod/quiz/lib.php -
  59   *    1. all reference to oldanswers removed
  60   *    2. all reference to quiz_multichoice table removed
  61   *    3. In shortanswer questions usecase is store in the qoption field
  62   *    4. In numeric questions store the range as two answers
  63   *    5. truefalse options are ignored
  64   *    6. For multichoice questions with more than one answer the qoption field is true
  65   *
  66   * @param object $question Contains question data like question, type and answers.
  67   * @param object $lesson
  68   * @param int $contextid
  69   * @return object Returns $result->error or $result->notice.
  70   **/
  71  function lesson_save_question_options($question, $lesson, $contextid) {
  72      global $DB;
  73  
  74      // These lines are required to ensure that all page types have
  75      // been loaded for the following switch
  76      if (!($lesson instanceof lesson)) {
  77          $lesson = new lesson($lesson);
  78      }
  79      $manager = lesson_page_type_manager::get($lesson);
  80  
  81      $timenow = time();
  82      $result = new stdClass();
  83      switch ($question->qtype) {
  84          case LESSON_PAGE_SHORTANSWER:
  85  
  86              $answers = array();
  87              $maxfraction = -1;
  88  
  89              // Insert all the new answers
  90              foreach ($question->answer as $key => $dataanswer) {
  91                  if ($dataanswer != "") {
  92                      $answer = new stdClass;
  93                      $answer->lessonid   = $question->lessonid;
  94                      $answer->pageid   = $question->id;
  95                      if ($question->fraction[$key] >=0.5) {
  96                          $answer->jumpto = LESSON_NEXTPAGE;
  97                      }
  98                      $answer->timecreated   = $timenow;
  99                      $answer->grade = $question->fraction[$key] * 100;
 100                      $answer->answer   = $dataanswer;
 101                      $answer->response = $question->feedback[$key]['text'];
 102                      $answer->responseformat = $question->feedback[$key]['format'];
 103                      $answer->id = $DB->insert_record("lesson_answers", $answer);
 104                      lesson_import_question_files('response', $question->feedback[$key], $answer, $contextid);
 105                      $answers[] = $answer->id;
 106                      if ($question->fraction[$key] > $maxfraction) {
 107                          $maxfraction = $question->fraction[$key];
 108                      }
 109                  }
 110              }
 111  
 112  
 113              /// Perform sanity checks on fractional grades
 114              if ($maxfraction != 1) {
 115                  $maxfraction = $maxfraction * 100;
 116                  $result->notice = get_string("fractionsnomax", "lesson", $maxfraction);
 117                  return $result;
 118              }
 119              break;
 120  
 121          case LESSON_PAGE_NUMERICAL:   // Note similarities to shortanswer.
 122  
 123              $answers = array();
 124              $maxfraction = -1;
 125  
 126  
 127              // for each answer store the pair of min and max values even if they are the same
 128              foreach ($question->answer as $key => $dataanswer) {
 129                  if ($dataanswer != "") {
 130                      $answer = new stdClass;
 131                      $answer->lessonid   = $question->lessonid;
 132                      $answer->pageid   = $question->id;
 133                      $answer->jumpto = LESSON_NEXTPAGE;
 134                      $answer->timecreated   = $timenow;
 135                      $answer->grade = $question->fraction[$key] * 100;
 136                      $min = $question->answer[$key] - $question->tolerance[$key];
 137                      $max = $question->answer[$key] + $question->tolerance[$key];
 138                      $answer->answer   = $min.":".$max;
 139                      // $answer->answer   = $question->min[$key].":".$question->max[$key]; original line for min/max
 140                      $answer->response = $question->feedback[$key]['text'];
 141                      $answer->responseformat = $question->feedback[$key]['format'];
 142                      $answer->id = $DB->insert_record("lesson_answers", $answer);
 143                      lesson_import_question_files('response', $question->feedback[$key], $answer, $contextid);
 144  
 145                      $answers[] = $answer->id;
 146                      if ($question->fraction[$key] > $maxfraction) {
 147                          $maxfraction = $question->fraction[$key];
 148                      }
 149                  }
 150              }
 151  
 152              /// Perform sanity checks on fractional grades
 153              if ($maxfraction != 1) {
 154                  $maxfraction = $maxfraction * 100;
 155                  $result->notice = get_string("fractionsnomax", "lesson", $maxfraction);
 156                  return $result;
 157              }
 158          break;
 159  
 160  
 161          case LESSON_PAGE_TRUEFALSE:
 162  
 163              // the truth
 164              $answer = new stdClass();
 165              $answer->lessonid   = $question->lessonid;
 166              $answer->pageid = $question->id;
 167              $answer->timecreated   = $timenow;
 168              $answer->answer = get_string("true", "lesson");
 169              $answer->grade = $question->correctanswer * 100;
 170              if ($answer->grade > 50 ) {
 171                  $answer->jumpto = LESSON_NEXTPAGE;
 172              }
 173              if (isset($question->feedbacktrue)) {
 174                  $answer->response = $question->feedbacktrue['text'];
 175                  $answer->responseformat = $question->feedbacktrue['format'];
 176              }
 177              $answer->id = $DB->insert_record("lesson_answers", $answer);
 178              lesson_import_question_files('response', $question->feedbacktrue, $answer, $contextid);
 179  
 180              // the lie
 181              $answer = new stdClass;
 182              $answer->lessonid   = $question->lessonid;
 183              $answer->pageid = $question->id;
 184              $answer->timecreated   = $timenow;
 185              $answer->answer = get_string("false", "lesson");
 186              $answer->grade = (1 - (int)$question->correctanswer) * 100;
 187              if ($answer->grade > 50 ) {
 188                  $answer->jumpto = LESSON_NEXTPAGE;
 189              }
 190              if (isset($question->feedbackfalse)) {
 191                  $answer->response = $question->feedbackfalse['text'];
 192                  $answer->responseformat = $question->feedbackfalse['format'];
 193              }
 194              $answer->id = $DB->insert_record("lesson_answers", $answer);
 195              lesson_import_question_files('response', $question->feedbackfalse, $answer, $contextid);
 196  
 197            break;
 198  
 199          case LESSON_PAGE_MULTICHOICE:
 200  
 201              $totalfraction = 0;
 202              $maxfraction = -1;
 203  
 204              $answers = array();
 205  
 206              // Insert all the new answers
 207              foreach ($question->answer as $key => $dataanswer) {
 208                  if ($dataanswer != "") {
 209                      $answer = new stdClass;
 210                      $answer->lessonid   = $question->lessonid;
 211                      $answer->pageid   = $question->id;
 212                      $answer->timecreated   = $timenow;
 213                      $answer->grade = $question->fraction[$key] * 100;
 214                      // changed some defaults
 215                      /* Original Code
 216                      if ($answer->grade > 50 ) {
 217                          $answer->jumpto = LESSON_NEXTPAGE;
 218                      }
 219                      Replaced with:                    */
 220                      if ($answer->grade > 50 ) {
 221                          $answer->jumpto = LESSON_NEXTPAGE;
 222                          $answer->score = 1;
 223                      }
 224                      // end Replace
 225                      $answer->answer   = $dataanswer['text'];
 226                      $answer->answerformat   = $dataanswer['format'];
 227                      $answer->response = $question->feedback[$key]['text'];
 228                      $answer->responseformat = $question->feedback[$key]['format'];
 229                      $answer->id = $DB->insert_record("lesson_answers", $answer);
 230                      lesson_import_question_files('answer', $dataanswer, $answer, $contextid);
 231                      lesson_import_question_files('response', $question->feedback[$key], $answer, $contextid);
 232  
 233                      // for Sanity checks
 234                      if ($question->fraction[$key] > 0) {
 235                          $totalfraction += $question->fraction[$key];
 236                      }
 237                      if ($question->fraction[$key] > $maxfraction) {
 238                          $maxfraction = $question->fraction[$key];
 239                      }
 240                  }
 241              }
 242  
 243              /// Perform sanity checks on fractional grades
 244              if ($question->single) {
 245                  if ($maxfraction != 1) {
 246                      $maxfraction = $maxfraction * 100;
 247                      $result->notice = get_string("fractionsnomax", "lesson", $maxfraction);
 248                      return $result;
 249                  }
 250              } else {
 251                  $totalfraction = round($totalfraction,2);
 252                  if ($totalfraction != 1) {
 253                      $totalfraction = $totalfraction * 100;
 254                      $result->notice = get_string("fractionsaddwrong", "lesson", $totalfraction);
 255                      return $result;
 256                  }
 257              }
 258          break;
 259  
 260          case LESSON_PAGE_MATCHING:
 261  
 262              $subquestions = array();
 263  
 264              $defaultanswer = new stdClass;
 265              $defaultanswer->lessonid   = $question->lessonid;
 266              $defaultanswer->pageid   = $question->id;
 267              $defaultanswer->timecreated   = $timenow;
 268              $defaultanswer->grade = 0;
 269  
 270              // The first answer should always be the correct answer
 271              $correctanswer = clone($defaultanswer);
 272              $correctanswer->answer = get_string('thatsthecorrectanswer', 'lesson');
 273              $correctanswer->jumpto = LESSON_NEXTPAGE;
 274              $DB->insert_record("lesson_answers", $correctanswer);
 275  
 276              // The second answer should always be the wrong answer
 277              $wronganswer = clone($defaultanswer);
 278              $wronganswer->answer = get_string('thatsthewronganswer', 'lesson');
 279              $DB->insert_record("lesson_answers", $wronganswer);
 280  
 281              $i = 0;
 282              // Insert all the new question+answer pairs
 283              foreach ($question->subquestions as $key => $questiontext) {
 284                  $answertext = $question->subanswers[$key];
 285                  if (!empty($questiontext) and !empty($answertext)) {
 286                      $answer = clone($defaultanswer);
 287                      $answer->answer = $questiontext['text'];
 288                      $answer->answerformat   = $questiontext['format'];
 289                      $answer->response   = $answertext;
 290                      if ($i == 0) {
 291                          // first answer contains the correct answer jump
 292                          $answer->jumpto = LESSON_NEXTPAGE;
 293                      }
 294                      $answer->id = $DB->insert_record("lesson_answers", $answer);
 295                      lesson_import_question_files('answer', $questiontext, $answer, $contextid);
 296                      $subquestions[] = $answer->id;
 297                      $i++;
 298                  }
 299              }
 300  
 301              if (count($subquestions) < 3) {
 302                  $result->notice = get_string("notenoughsubquestions", "lesson");
 303                  return $result;
 304              }
 305              break;
 306          default:
 307              $result->error = "Unsupported question type ($question->qtype)!";
 308              return $result;
 309      }
 310      return true;
 311  }
 312  
 313  
 314  class qformat_default {
 315  
 316      var $displayerrors = true;
 317      var $category = null;
 318      var $questionids = array();
 319      protected $importcontext = null;
 320      var $qtypeconvert = array('numerical'   => LESSON_PAGE_NUMERICAL,
 321                                 'multichoice' => LESSON_PAGE_MULTICHOICE,
 322                                 'truefalse'   => LESSON_PAGE_TRUEFALSE,
 323                                 'shortanswer' => LESSON_PAGE_SHORTANSWER,
 324                                 'match'       => LESSON_PAGE_MATCHING
 325                                );
 326  
 327      // Importing functions
 328      function provide_import() {
 329          return false;
 330      }
 331  
 332      function set_importcontext($context) {
 333          $this->importcontext = $context;
 334      }
 335  
 336      /**
 337       * Handle parsing error
 338       *
 339       * @param string $message information about error
 340       * @param string $text imported text that triggered the error
 341       * @param string $questionname imported question name
 342       */
 343      protected function error($message, $text='', $questionname='') {
 344          $importerrorquestion = get_string('importerrorquestion', 'question');
 345  
 346          echo "<div class=\"importerror\">\n";
 347          echo "<strong>$importerrorquestion $questionname</strong>";
 348          if (!empty($text)) {
 349              $text = s($text);
 350              echo "<blockquote>$text</blockquote>\n";
 351          }
 352          echo "<strong>$message</strong>\n";
 353          echo "</div>";
 354      }
 355  
 356      function importpreprocess() {
 357          // Does any pre-processing that may be desired
 358          return true;
 359      }
 360  
 361      function importprocess($filename, $lesson, $pageid) {
 362          global $DB, $OUTPUT;
 363  
 364      /// Processes a given file.  There's probably little need to change this
 365          $timenow = time();
 366  
 367          if (! $lines = $this->readdata($filename)) {
 368              echo $OUTPUT->notification("File could not be read, or was empty");
 369              return false;
 370          }
 371  
 372          if (! $questions = $this->readquestions($lines)) {   // Extract all the questions
 373              echo $OUTPUT->notification("There are no questions in this file!");
 374              return false;
 375          }
 376  
 377          //Avoid category as question type
 378          echo $OUTPUT->notification(get_string('importcount', 'lesson',
 379                  $this->count_questions($questions)), 'notifysuccess');
 380  
 381          $count = 0;
 382          $addquestionontop = false;
 383          if ($pageid == 0) {
 384              $addquestionontop = true;
 385              $updatelessonpage = $DB->get_record('lesson_pages', array('lessonid' => $lesson->id, 'prevpageid' => 0));
 386          } else {
 387              $updatelessonpage = $DB->get_record('lesson_pages', array('lessonid' => $lesson->id, 'id' => $pageid));
 388          }
 389  
 390          $unsupportedquestions = 0;
 391  
 392          foreach ($questions as $question) {   // Process and store each question
 393              switch ($question->qtype) {
 394                  //TODO: Bad way to bypass category in data... Quickfix for MDL-27964
 395                  case 'category':
 396                      break;
 397                  // the good ones
 398                  case 'shortanswer' :
 399                  case 'numerical' :
 400                  case 'truefalse' :
 401                  case 'multichoice' :
 402                  case 'match' :
 403                      $count++;
 404  
 405                      //Show nice formated question in one line.
 406                      echo "<hr><p><b>$count</b>. ".$this->format_question_text($question)."</p>";
 407  
 408                      $newpage = new stdClass;
 409                      $newpage->lessonid = $lesson->id;
 410                      $newpage->qtype = $this->qtypeconvert[$question->qtype];
 411                      switch ($question->qtype) {
 412                          case 'shortanswer' :
 413                              if (isset($question->usecase)) {
 414                                  $newpage->qoption = $question->usecase;
 415                              }
 416                              break;
 417                          case 'multichoice' :
 418                              if (isset($question->single)) {
 419                                  $newpage->qoption = !$question->single;
 420                              }
 421                              break;
 422                      }
 423                      $newpage->timecreated = $timenow;
 424                      if ($question->name != $question->questiontext) {
 425                          $newpage->title = $question->name;
 426                      } else {
 427                          $newpage->title = "Page $count";
 428                      }
 429                      $newpage->contents = $question->questiontext;
 430                      $newpage->contentsformat = isset($question->questionformat) ? $question->questionformat : FORMAT_HTML;
 431  
 432                      // set up page links
 433                      if ($pageid) {
 434                          // the new page follows on from this page
 435                          if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) {
 436                              print_error('invalidpageid', 'lesson');
 437                          }
 438                          $newpage->prevpageid = $pageid;
 439                          $newpage->nextpageid = $page->nextpageid;
 440                          // insert the page and reset $pageid
 441                          $newpageid = $DB->insert_record("lesson_pages", $newpage);
 442                          // update the linked list
 443                          $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid));
 444                      } else {
 445                          // new page is the first page
 446                          // get the existing (first) page (if any)
 447                          $params = array ("lessonid" => $lesson->id, "prevpageid" => 0);
 448                          if (!$page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) {
 449                              // there are no existing pages
 450                              $newpage->prevpageid = 0; // this is a first page
 451                              $newpage->nextpageid = 0; // this is the only page
 452                              $newpageid = $DB->insert_record("lesson_pages", $newpage);
 453                          } else {
 454                              // there are existing pages put this at the start
 455                              $newpage->prevpageid = 0; // this is a first page
 456                              $newpage->nextpageid = $page->id;
 457                              $newpageid = $DB->insert_record("lesson_pages", $newpage);
 458                              // update the linked list
 459                              $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->id));
 460                          }
 461                      }
 462  
 463                      // reset $pageid and put the page ID in $question, used in save_question_option()
 464                      $pageid = $newpageid;
 465                      $question->id = $newpageid;
 466  
 467                      $this->questionids[] = $question->id;
 468  
 469                      // Import images in question text.
 470                      if (isset($question->questiontextitemid)) {
 471                          $questiontext = file_save_draft_area_files($question->questiontextitemid,
 472                                  $this->importcontext->id, 'mod_lesson', 'page_contents', $newpageid,
 473                                  null , $question->questiontext);
 474                          // Update content with recoded urls.
 475                          $DB->set_field("lesson_pages", "contents", $questiontext, array("id" => $newpageid));
 476                      }
 477  
 478                      // Now to save all the answers and type-specific options
 479  
 480                      $question->lessonid = $lesson->id; // needed for foreign key
 481                      $question->qtype = $this->qtypeconvert[$question->qtype];
 482                      $result = lesson_save_question_options($question, $lesson, $this->importcontext->id);
 483  
 484                      if (!empty($result->error)) {
 485                          echo $OUTPUT->notification($result->error);
 486                          return false;
 487                      }
 488  
 489                      if (!empty($result->notice)) {
 490                          echo $OUTPUT->notification($result->notice);
 491                          return true;
 492                      }
 493                      break;
 494              // the Bad ones
 495                  default :
 496                      $unsupportedquestions++;
 497                      break;
 498              }
 499          }
 500          // Update the prev links if there were existing pages.
 501          if (!empty($updatelessonpage)) {
 502              if ($addquestionontop) {
 503                  $DB->set_field("lesson_pages", "prevpageid", $pageid, array("id" => $updatelessonpage->id));
 504              } else {
 505                  $DB->set_field("lesson_pages", "prevpageid", $pageid, array("id" => $updatelessonpage->nextpageid));
 506              }
 507          }
 508          if ($unsupportedquestions) {
 509              echo $OUTPUT->notification(get_string('unknownqtypesnotimported', 'lesson', $unsupportedquestions));
 510          }
 511          return true;
 512      }
 513  
 514      /**
 515       * Count all non-category questions in the questions array.
 516       *
 517       * @param array questions An array of question objects.
 518       * @return int The count.
 519       *
 520       */
 521      protected function count_questions($questions) {
 522          $count = 0;
 523          if (!is_array($questions)) {
 524              return $count;
 525          }
 526          foreach ($questions as $question) {
 527              if (!is_object($question) || !isset($question->qtype) ||
 528                      ($question->qtype == 'category')) {
 529                  continue;
 530              }
 531              $count++;
 532          }
 533          return $count;
 534      }
 535  
 536      function readdata($filename) {
 537      /// Returns complete file with an array, one item per line
 538  
 539          if (is_readable($filename)) {
 540              $filearray = file($filename);
 541  
 542              /// Check for Macintosh OS line returns (ie file on one line), and fix
 543              if (preg_match("/\r/", $filearray[0]) AND !preg_match("/\n/", $filearray[0])) {
 544                  return explode("\r", $filearray[0]);
 545              } else {
 546                  return $filearray;
 547              }
 548          }
 549          return false;
 550      }
 551  
 552      protected function readquestions($lines) {
 553      /// Parses an array of lines into an array of questions,
 554      /// where each item is a question object as defined by
 555      /// readquestion().   Questions are defined as anything
 556      /// between blank lines.
 557  
 558          $questions = array();
 559          $currentquestion = array();
 560  
 561          foreach ($lines as $line) {
 562              $line = trim($line);
 563              if (empty($line)) {
 564                  if (!empty($currentquestion)) {
 565                      if ($question = $this->readquestion($currentquestion)) {
 566                          $questions[] = $question;
 567                      }
 568                      $currentquestion = array();
 569                  }
 570              } else {
 571                  $currentquestion[] = $line;
 572              }
 573          }
 574  
 575          if (!empty($currentquestion)) {  // There may be a final question
 576              if ($question = $this->readquestion($currentquestion)) {
 577                  $questions[] = $question;
 578              }
 579          }
 580  
 581          return $questions;
 582      }
 583  
 584  
 585      protected function readquestion($lines) {
 586      /// Given an array of lines known to define a question in
 587      /// this format, this function converts it into a question
 588      /// object suitable for processing and insertion into Moodle.
 589  
 590          echo "<p>This flash question format has not yet been completed!</p>";
 591  
 592          return null;
 593      }
 594  
 595      /**
 596       * Construct a reasonable default question name, based on the start of the question text.
 597       * @param string $questiontext the question text.
 598       * @param string $default default question name to use if the constructed one comes out blank.
 599       * @return string a reasonable question name.
 600       */
 601      public function create_default_question_name($questiontext, $default) {
 602          $name = $this->clean_question_name(shorten_text($questiontext, 80));
 603          if ($name) {
 604              return $name;
 605          } else {
 606              return $default;
 607          }
 608      }
 609  
 610      /**
 611       * Ensure that a question name does not contain anything nasty, and will fit in the DB field.
 612       * @param string $name the raw question name.
 613       * @return string a safe question name.
 614       */
 615      public function clean_question_name($name) {
 616          $name = clean_param($name, PARAM_TEXT); // Matches what the question editing form does.
 617          $name = trim($name);
 618          $trimlength = 251;
 619          while (core_text::strlen($name) > 255 && $trimlength > 0) {
 620              $name = shorten_text($name, $trimlength);
 621              $trimlength -= 10;
 622          }
 623          return $name;
 624      }
 625  
 626      function defaultquestion() {
 627      // returns an "empty" question
 628      // Somewhere to specify question parameters that are not handled
 629      // by import but are required db fields.
 630      // This should not be overridden.
 631          global $CFG;
 632  
 633          $question = new stdClass();
 634          $question->shuffleanswers = get_config('quiz', 'shuffleanswers');
 635          $question->defaultmark = 1;
 636          $question->image = "";
 637          $question->usecase = 0;
 638          $question->multiplier = array();
 639          $question->generalfeedback = '';
 640          $question->correctfeedback = '';
 641          $question->partiallycorrectfeedback = '';
 642          $question->incorrectfeedback = '';
 643          $question->answernumbering = 'abc';
 644          $question->penalty = 0.1;
 645          $question->length = 1;
 646          $question->qoption = 0;
 647          $question->layout = 1;
 648  
 649          // this option in case the questiontypes class wants
 650          // to know where the data came from
 651          $question->export_process = true;
 652          $question->import_process = true;
 653  
 654          return $question;
 655      }
 656  
 657      function importpostprocess() {
 658          /// Does any post-processing that may be desired
 659          /// Argument is a simple array of question ids that
 660          /// have just been added.
 661          return true;
 662      }
 663  
 664      /**
 665       * Convert the question text to plain text, so it can safely be displayed
 666       * during import to let the user see roughly what is going on.
 667       */
 668      protected function format_question_text($question) {
 669          $formatoptions = new stdClass();
 670          $formatoptions->noclean = true;
 671          // The html_to_text call strips out all URLs, but format_text complains
 672          // if it finds @@PLUGINFILE@@ tokens. So, we need to replace
 673          // @@PLUGINFILE@@ with a real URL, but it doesn't matter what.
 674          // We use http://example.com/.
 675          $text = str_replace('@@PLUGINFILE@@/', 'http://example.com/', $question->questiontext);
 676          return html_to_text(format_text($text,
 677                  $question->questiontextformat, $formatoptions), 0, false);
 678      }
 679  
 680      /**
 681       * Since the lesson module tries to re-use the question bank import classes in
 682       * a crazy way, this is necessary to stop things breaking.
 683       */
 684      protected function add_blank_combined_feedback($question) {
 685          return $question;
 686      }
 687  }
 688  
 689  
 690  /**
 691   * Since the lesson module tries to re-use the question bank import classes in
 692   * a crazy way, this is necessary to stop things breaking. This should be exactly
 693   * the same as the class defined in question/format.php.
 694   */
 695  class qformat_based_on_xml extends qformat_default {
 696      /**
 697       * A lot of imported files contain unwanted entities.
 698       * This method tries to clean up all known problems.
 699       * @param string str string to correct
 700       * @return string the corrected string
 701       */
 702      public function cleaninput($str) {
 703  
 704          $html_code_list = array(
 705              "&#039;" => "'",
 706              "&#8217;" => "'",
 707              "&#8220;" => "\"",
 708              "&#8221;" => "\"",
 709              "&#8211;" => "-",
 710              "&#8212;" => "-",
 711          );
 712          $str = strtr($str, $html_code_list);
 713          // Use core_text entities_to_utf8 function to convert only numerical entities.
 714          $str = core_text::entities_to_utf8($str, false);
 715          return $str;
 716      }
 717  
 718      /**
 719       * Return the array moodle is expecting
 720       * for an HTML text. No processing is done on $text.
 721       * qformat classes that want to process $text
 722       * for instance to import external images files
 723       * and recode urls in $text must overwrite this method.
 724       * @param array $text some HTML text string
 725       * @return array with keys text, format and files.
 726       */
 727      public function text_field($text) {
 728          return array(
 729              'text' => trim($text),
 730              'format' => FORMAT_HTML,
 731              'files' => array(),
 732          );
 733      }
 734  
 735      /**
 736       * Return the value of a node, given a path to the node
 737       * if it doesn't exist return the default value.
 738       * @param array xml data to read
 739       * @param array path path to node expressed as array
 740       * @param mixed default
 741       * @param bool istext process as text
 742       * @param string error if set value must exist, return false and issue message if not
 743       * @return mixed value
 744       */
 745      public function getpath($xml, $path, $default, $istext=false, $error='') {
 746          foreach ($path as $index) {
 747              if (!isset($xml[$index])) {
 748                  if (!empty($error)) {
 749                      $this->error($error);
 750                      return false;
 751                  } else {
 752                      return $default;
 753                  }
 754              }
 755  
 756              $xml = $xml[$index];
 757          }
 758  
 759          if ($istext) {
 760              if (!is_string($xml)) {
 761                  $this->error(get_string('invalidxml', 'qformat_xml'));
 762              }
 763              $xml = trim($xml);
 764          }
 765  
 766          return $xml;
 767      }
 768  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1