Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * XHTML question exporter.
  19   *
  20   * @package    qformat_xhtml
  21   * @copyright  2005 Howard Miller
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  
  29  /**
  30   * XHTML question exporter.
  31   *
  32   * Exports questions as static HTML.
  33   *
  34   * @copyright  2005 Howard Miller
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class qformat_xhtml extends qformat_default {
  38  
  39      public function provide_export() {
  40          return true;
  41      }
  42  
  43      protected function repchar($text) {
  44          return $text;
  45      }
  46  
  47      protected function writequestion($question) {
  48          global $OUTPUT;
  49          // Turns question into string.
  50          // Question reflects database fields for general question and specific to type.
  51  
  52          // If a category switch, just ignore.
  53          if ($question->qtype=='category') {
  54              return '';
  55          }
  56  
  57          // Initial string.
  58          $expout = "";
  59          $id = $question->id;
  60  
  61          // Add comment and div tags.
  62          $expout .= "<!-- question: {$id}  name: {$question->name} -->\n";
  63          $expout .= "<div class=\"question\">\n";
  64  
  65          // Add header.
  66          $expout .= "<h3>{$question->name}</h3>\n";
  67  
  68          // Format and add the question text.
  69          $text = question_rewrite_question_preview_urls($question->questiontext, $question->id,
  70                  $question->contextid, 'question', 'questiontext', $question->id,
  71                  $question->contextid, 'qformat_xhtml');
  72          $expout .= '<p class="questiontext">' . format_text($text,
  73                  $question->questiontextformat, array('noclean' => true)) . "</p>\n";
  74  
  75          // Selection depends on question type.
  76          switch($question->qtype) {
  77              case 'truefalse':
  78                  $sttrue = get_string('true', 'qtype_truefalse');
  79                  $stfalse = get_string('false', 'qtype_truefalse');
  80                  $expout .= "<ul class=\"truefalse\">\n";
  81                  $expout .= "  <li><input name=\"quest_{$id}\" type=\"radio\" value=\"{$sttrue}\" />{$sttrue}</li>\n";
  82                  $expout .= "  <li><input name=\"quest_{$id}\" type=\"radio\" value=\"{$stfalse}\" />{$stfalse}</li>\n";
  83                  $expout .= "</ul>\n";
  84                  break;
  85              case 'multichoice':
  86                  $expout .= "<ul class=\"multichoice\">\n";
  87                  foreach ($question->options->answers as $answer) {
  88                      $answertext = $this->repchar( $answer->answer );
  89                      if ($question->options->single) {
  90                          $expout .= "  <li><input name=\"quest_{$id}\" type=\"radio\" value=\""
  91                                  . s($answertext) . "\" />{$answertext}</li>\n";
  92                      } else {
  93                          $expout .= "  <li><input name=\"quest_{$id}\" type=\"checkbox\" value=\""
  94                                  . s($answertext) . "\" />{$answertext}</li>\n";
  95                      }
  96                  }
  97                  $expout .= "</ul>\n";
  98                  break;
  99              case 'shortanswer':
 100                  $expout .= html_writer::start_tag('ul', array('class' => 'shortanswer'));
 101                  $expout .= html_writer::start_tag('li');
 102                  $expout .= html_writer::label(get_string('answer'), 'quest_'.$id, false, array('class' => 'accesshide'));
 103                  $expout .= html_writer::empty_tag('input', array('id' => "quest_{$id}", 'name' => "quest_{$id}", 'type' => 'text'));
 104                  $expout .= html_writer::end_tag('li');
 105                  $expout .= html_writer::end_tag('ul');
 106                  break;
 107              case 'numerical':
 108                  $expout .= html_writer::start_tag('ul', array('class' => 'numerical'));
 109                  $expout .= html_writer::start_tag('li');
 110                  $expout .= html_writer::label(get_string('answer'), 'quest_'.$id, false, array('class' => 'accesshide'));
 111                  $expout .= html_writer::empty_tag('input', array('id' => "quest_{$id}", 'name' => "quest_{$id}", 'type' => 'text'));
 112                  $expout .= html_writer::end_tag('li');
 113                  $expout .= html_writer::end_tag('ul');
 114                  break;
 115              case 'match':
 116                  $expout .= html_writer::start_tag('ul', array('class' => 'match'));
 117  
 118                  // Build answer list.
 119                  $answerlist = array();
 120                  foreach ($question->options->subquestions as $subquestion) {
 121                      $answerlist[] = $this->repchar( $subquestion->answertext );
 122                  }
 123                  shuffle( $answerlist ); // Random display order.
 124  
 125                  // Build select options.
 126                  $selectoptions = array();
 127                  foreach ($answerlist as $ans) {
 128                      $selectoptions[s($ans)] = s($ans);
 129                  }
 130  
 131                  // Display.
 132                  $option = 0;
 133                  foreach ($question->options->subquestions as $subquestion) {
 134                      // Build drop down for answers.
 135                      $questiontext = $this->repchar( $subquestion->questiontext );
 136                      if ($questiontext != '') {
 137                          $dropdown = html_writer::label(get_string('answer', 'qtype_match', $option+1), 'quest_'.$id.'_'.$option,
 138                                  false, array('class' => 'accesshide'));
 139                          $dropdown .= html_writer::select($selectoptions, "quest_{$id}_{$option}", '', false,
 140                                  array('id' => "quest_{$id}_{$option}"));
 141                          $expout .= html_writer::tag('li', $questiontext);
 142                          $expout .= $dropdown;
 143                          $option++;
 144                      }
 145                  }
 146                  $expout .= html_writer::end_tag('ul');
 147                  break;
 148              case 'description':
 149                  break;
 150              case 'multianswer':
 151              default:
 152                  $expout .= "<!-- export of {$question->qtype} type is not supported  -->\n";
 153          }
 154          // Close off div.
 155          $expout .= "</div>\n\n\n";
 156          return $expout;
 157      }
 158  
 159  
 160      protected function presave_process($content) {
 161          // Override method to allow us to add xhtml headers and footers.
 162  
 163          global $CFG;
 164  
 165          // Get css bit.
 166          $csslines = file( "{$CFG->dirroot}/question/format/xhtml/xhtml.css" );
 167          $css = implode( ' ', $csslines );
 168  
 169          $xp =  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n";
 170          $xp .= "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
 171          $xp .= "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
 172          $xp .= "<head>\n";
 173          $xp .= "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" />\n";
 174          $xp .= "<title>Moodle Quiz XHTML Export</title>\n";
 175          $xp .= "<style type=\"text/css\">\n";
 176          $xp .= $css;
 177          $xp .= "</style>\n";
 178          $xp .= "</head>\n";
 179          $xp .= "<body>\n";
 180          $xp .= "<form action=\"...REPLACE ME...\" method=\"post\">\n\n";
 181          $xp .= $content;
 182          $xp .= "<p class=\"submit\">\n";
 183          $xp .= "  <input type=\"submit\" />\n";
 184          $xp .= "</p>\n";
 185          $xp .= "</form>\n";
 186          $xp .= "</body>\n";
 187          $xp .= "</html>\n";
 188  
 189          return $xp;
 190      }
 191  
 192      public function export_file_extension() {
 193          return '.html';
 194      }
 195  }