mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 14:27:22 +01:00
question import/export: MDL-20299 fatal error cause by hotpot format changes
Replaced copy and paste code from mod/hotpot/lib.php with a require_once.
This commit is contained in:
parent
3d39d775fa
commit
eaf3fd7a45
@ -12,6 +12,7 @@
|
||||
* @package questionbank
|
||||
* @subpackage importexport
|
||||
*/
|
||||
require_once($CFG->dirroot . '/mod/hotpot/lib.php');
|
||||
|
||||
class qformat_hotpot extends qformat_default {
|
||||
|
||||
@ -507,284 +508,3 @@ class qformat_hotpot extends qformat_default {
|
||||
return $str;
|
||||
}
|
||||
} // end class
|
||||
|
||||
// get the standard XML parser supplied with Moodle
|
||||
require_once("$CFG->libdir/xmlize.php");
|
||||
|
||||
class hotpot_xml_tree {
|
||||
function hotpot_xml_tree($str, $xml_root='') {
|
||||
if (empty($str)) {
|
||||
$this->xml = array();
|
||||
} else {
|
||||
// encode htmlentities in JCloze
|
||||
$this->encode_cdata($str, 'gap-fill');
|
||||
// xmlize (=convert xml to tree)
|
||||
$this->xml = xmlize($str, 0);
|
||||
}
|
||||
$this->xml_root = $xml_root;
|
||||
}
|
||||
function xml_value($tags, $more_tags="[0]['#']") {
|
||||
|
||||
$value = null;
|
||||
if (isset($this->xml) && is_array($this->xml)) {
|
||||
|
||||
$all_tags = $this->xml_root;
|
||||
if ($tags) {
|
||||
$all_tags .= "['".str_replace(",", "'][0]['#']['", $tags)."']";
|
||||
}
|
||||
$all_tags .= $more_tags;
|
||||
|
||||
$pos = strrpos($all_tags, '[');
|
||||
if ($pos===false) {
|
||||
$most_tags = ''; // shouldn't happen !!
|
||||
} else {
|
||||
$most_tags = substr($all_tags, 0, $pos);
|
||||
}
|
||||
|
||||
eval('if (isset($this->xml'.$most_tags.') && is_array($this->xml'.$most_tags.') && isset($this->xml'.$all_tags.')) {'
|
||||
.'$value = &$this->xml'.$all_tags.';'
|
||||
.'} else {'
|
||||
.'$value = null;'
|
||||
.'}'
|
||||
);
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
|
||||
// decode angle brackets and ampersands
|
||||
$value = strtr($value, array('<'=>'<', '>'=>'>', '&'=>'&'));
|
||||
|
||||
// remove white space between <table>, <ul|OL|DL> and <OBJECT|EMBED> parts
|
||||
// (so it doesn't get converted to <br />)
|
||||
$htmltags = '('
|
||||
. 'TABLE|/?CAPTION|/?COL|/?COLGROUP|/?TBODY|/?TFOOT|/?THEAD|/?TD|/?TH|/?TR'
|
||||
. '|OL|UL|/?LI'
|
||||
. '|DL|/?DT|/?DD'
|
||||
. '|EMBED|OBJECT|APPLET|/?PARAM'
|
||||
//. '|SELECT|/?OPTION'
|
||||
//. '|FIELDSET|/?LEGEND'
|
||||
//. '|FRAMESET|/?FRAME'
|
||||
. ')'
|
||||
;
|
||||
$search = '#(<'.$htmltags.'[^>]*'.'>)\s+'.'(?='.'<'.')#is';
|
||||
$value = preg_replace($search, '\\1', $value);
|
||||
|
||||
// replace remaining newlines with <br />
|
||||
$value = str_replace("\n", '<br />', $value);
|
||||
|
||||
// encode unicode characters as HTML entities
|
||||
// (in particular, accented charaters that have not been encoded by HP)
|
||||
|
||||
// multibyte unicode characters can be detected by checking the hex value of the first character
|
||||
// 00 - 7F : ascii char (roman alphabet + punctuation)
|
||||
// 80 - BF : byte 2, 3 or 4 of a unicode char
|
||||
// C0 - DF : 1st byte of 2-byte char
|
||||
// E0 - EF : 1st byte of 3-byte char
|
||||
// F0 - FF : 1st byte of 4-byte char
|
||||
// if the string doesn't match the above, it might be
|
||||
// 80 - FF : single-byte, non-ascii char
|
||||
$search = '#('.'[\xc0-\xdf][\x80-\xbf]'.'|'.'[\xe0-\xef][\x80-\xbf]{2}'.'|'.'[\xf0-\xff][\x80-\xbf]{3}'.'|'.'[\x80-\xff]'.')#se';
|
||||
$value = preg_replace($search, "hotpot_utf8_to_html_entity('\\1')", $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
function encode_cdata(&$str, $tag) {
|
||||
|
||||
// conversion tables
|
||||
static $HTML_ENTITIES = array(
|
||||
''' => "'",
|
||||
'"' => '"',
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
'&' => '&',
|
||||
);
|
||||
static $ILLEGAL_STRINGS = array(
|
||||
"\r" => '',
|
||||
"\n" => '<br />',
|
||||
']]>' => ']]>',
|
||||
);
|
||||
|
||||
// extract the $tag from the $str(ing), if possible
|
||||
$pattern = '|(^.*<'.$tag.'[^>]*)(>.*<)(/'.$tag.'>.*$)|is';
|
||||
if (preg_match($pattern, $str, $matches)) {
|
||||
|
||||
// encode problematic CDATA chars and strings
|
||||
$matches[2] = strtr($matches[2], $ILLEGAL_STRINGS);
|
||||
|
||||
|
||||
// if there are any ampersands in "open text"
|
||||
// surround them by CDATA start and end markers
|
||||
// (and convert HTML entities to plain text)
|
||||
$search = '/>([^<]*&[^<]*)</e';
|
||||
$replace = '"><![CDATA[".strtr("$1", $HTML_ENTITIES)."]]><"';
|
||||
$matches[2] = preg_replace($search, $replace, $matches[2]);
|
||||
|
||||
$str = $matches[1].$matches[2].$matches[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hotpot_charcode_to_utf8($charcode) {
|
||||
if ($charcode <= 0x7F) {
|
||||
// ascii char (roman alphabet + punctuation)
|
||||
return chr($charcode);
|
||||
}
|
||||
if ($charcode <= 0x7FF) {
|
||||
// 2-byte char
|
||||
return chr(($charcode >> 0x06) + 0xC0).chr(($charcode & 0x3F) + 128);
|
||||
}
|
||||
if ($charcode <= 0xFFFF) {
|
||||
// 3-byte char
|
||||
return chr(($charcode >> 0x0C) + 0xE0).chr((($charcode >> 0x06) & 0x3F) + 0x80).chr(($charcode & 0x3F) + 0x80);
|
||||
}
|
||||
if ($charcode <= 0x1FFFFF) {
|
||||
// 4-byte char
|
||||
return chr(($charcode >> 0x12) + 0xF0).chr((($charcode >> 0x0C) & 0x3F) + 0x80).chr((($charcode >> 0x06) & 0x3F) + 0x80).chr(($charcode & 0x3F) + 0x80);
|
||||
}
|
||||
// unidentified char code !!
|
||||
return ' ';
|
||||
}
|
||||
|
||||
function hotpot_utf8_to_html_entity($char) {
|
||||
// http://www.zend.com/codex.php?id=835&single=1
|
||||
|
||||
// array used to figure what number to decrement from character order value
|
||||
// according to number of characters used to map unicode to ascii by utf-8
|
||||
static $HOTPOT_UTF8_DECREMENT = array(
|
||||
1=>0, 2=>192, 3=>224, 4=>240
|
||||
);
|
||||
|
||||
// the number of bits to shift each character by
|
||||
static $HOTPOT_UTF8_SHIFT = array(
|
||||
1=>array(0=>0),
|
||||
2=>array(0=>6, 1=>0),
|
||||
3=>array(0=>12, 1=>6, 2=>0),
|
||||
4=>array(0=>18, 1=>12, 2=>6, 3=>0)
|
||||
);
|
||||
|
||||
$dec = 0;
|
||||
$len = strlen($char);
|
||||
for ($pos=0; $pos<$len; $pos++) {
|
||||
$ord = ord ($char{$pos});
|
||||
$ord -= ($pos ? 128 : $HOTPOT_UTF8_DECREMENT[$len]);
|
||||
$dec += ($ord << $HOTPOT_UTF8_SHIFT[$len][$pos]);
|
||||
}
|
||||
return '&#x'.sprintf('%04X', $dec).';';
|
||||
}
|
||||
|
||||
function hotpot_convert_relative_urls($str, $baseurl, $filename) {
|
||||
$tagopen = '(?:(<)|(<)|(&#x003C;))'; // left angle bracket
|
||||
$tagclose = '(?(2)>|(?(3)>|(?(4)&#x003E;)))'; // right angle bracket (to match left angle bracket)
|
||||
|
||||
$space = '\s+'; // at least one space
|
||||
$anychar = '(?:[^>]*?)'; // any character
|
||||
|
||||
$quoteopen = '("|"|&quot;)'; // open quote
|
||||
$quoteclose = '\\5'; // close quote (to match open quote)
|
||||
|
||||
$replace = "hotpot_convert_relative_url('".$baseurl."', '".$filename."', '\\1', '\\6', '\\7')";
|
||||
|
||||
$tags = array('script'=>'src', 'link'=>'href', 'a'=>'href','img'=>'src','param'=>'value', 'object'=>'data', 'embed'=>'src');
|
||||
foreach ($tags as $tag=>$attribute) {
|
||||
if ($tag=='param') {
|
||||
$url = '\S+?\.\S+?'; // must include a filename and have no spaces
|
||||
} else {
|
||||
$url = '.*?';
|
||||
}
|
||||
$search = "%($tagopen$tag$space$anychar$attribute=$quoteopen)($url)($quoteclose$anychar$tagclose)%ise";
|
||||
$str = preg_replace($search, $replace, $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
function hotpot_convert_relative_url($baseurl, $filename, $opentag, $url, $closetag, $depricated=true) {
|
||||
// catch <PARAM name="FlashVars" value="TheSound=soundfile.mp3">
|
||||
// ampersands can appear as "&", "&" or "&#x0026;amp;"
|
||||
if (preg_match('|^'.'\w+=[^&]+'.'('.'&((amp;#x0026;)?amp;)?'.'\w+=[^&]+)*'.'$|', $url)) {
|
||||
$query = $url;
|
||||
$url = '';
|
||||
$fragment = '';
|
||||
|
||||
// parse the $url into $matches
|
||||
// [1] path
|
||||
// [2] query string, if any
|
||||
// [3] anchor fragment, if any
|
||||
} else if (preg_match('|^'.'([^?]*)'.'((?:\\?[^#]*)?)'.'((?:#.*)?)'.'$|', $url, $matches)) {
|
||||
$url = $matches[1];
|
||||
$query = $matches[2];
|
||||
$fragment = $matches[3];
|
||||
|
||||
// there appears to be no query or fragment in this url
|
||||
} else {
|
||||
$query = '';
|
||||
$fragment = '';
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
$url = hotpot_convert_url($baseurl, $filename, $url, false);
|
||||
}
|
||||
|
||||
if ($query) {
|
||||
$search = '#'.'(file|src|thesound)='."([^&]+)".'#ise';
|
||||
$replace = "'\\1='.hotpot_convert_url('".$baseurl."','".$filename."','\\2')";
|
||||
$query = preg_replace($search, $replace, $query);
|
||||
}
|
||||
|
||||
$url = $opentag.$url.$query.$fragment.$closetag;
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
function hotpot_convert_url($baseurl, $filename, $url, $depricated=true) {
|
||||
// maintain a cache of converted urls
|
||||
static $HOTPOT_RELATIVE_URLS = array();
|
||||
|
||||
// is this an absolute url? (or javascript pseudo url)
|
||||
if (preg_match('%^(http://|/|javascript:)%i', $url)) {
|
||||
// do nothing
|
||||
|
||||
// has this relative url already been converted?
|
||||
} else if (isset($HOTPOT_RELATIVE_URLS[$url])) {
|
||||
$url = $HOTPOT_RELATIVE_URLS[$url];
|
||||
|
||||
} else {
|
||||
$relativeurl = $url;
|
||||
|
||||
// get the subdirectory, $dir, of the quiz $filename
|
||||
$dir = dirname($filename);
|
||||
|
||||
// allow for leading "./" and "../"
|
||||
while (preg_match('|^(\.{1,2})/(.*)$|', $url, $matches)) {
|
||||
if ($matches[1]=='..') {
|
||||
$dir = dirname($dir);
|
||||
}
|
||||
$url = $matches[2];
|
||||
}
|
||||
|
||||
// add subdirectory, $dir, to $baseurl, if necessary
|
||||
if ($dir && $dir<>'.') {
|
||||
$baseurl .= "$dir/";
|
||||
}
|
||||
|
||||
// prefix $url with $baseurl
|
||||
$url = "$baseurl$url";
|
||||
|
||||
// add url to cache
|
||||
$HOTPOT_RELATIVE_URLS[$relativeurl] = $url;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
// allow importing in Moodle v1.4 (and less)
|
||||
// same core functions but different class name
|
||||
if (!class_exists("quiz_file_format")) {
|
||||
class quiz_file_format extends qformat_default {
|
||||
function readquestions ($lines) {
|
||||
$format = new qformat_hotpot();
|
||||
return $format->readquestions($lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
Loading…
x
Reference in New Issue
Block a user