Questions can be exported into XML text files that include images encoded as base64.
This is a very convenient way to move quiz questions around between courses. Better thsi is the ONLY way to excahnge quiz questions that include imege files added through the "Image to display" field in the question editing form.
However, importing such files created by export feature fails for any picture that is not in the course root dir. If the questions point to any image file located within any subdir of the course root, the questions are imported but not imagefiles. If I create previously the image directory then then image files are uploaded correctly, but the "Image to display" field is not pointing to it.
I have traced this to a minor bug in function importimagefile( $path, $base64 ) located in /question/format.php
When the XML files is procesed for importing by /question/format/xml/xml.php, in function import_headers( $question ) by line 132:
$image = $this->getpath( $question, array('#','image',0,'#'), $qo->image );
$image_base64 = $this->getpath( $question, array('#','image_base64','0','#'),'' );
if (!empty($image_base64))
$qo->image will be the "Image to display" content, so it is essential that it contains the full path to the image file location, for instance "images/file.jpg".
However, importimagefile() function fails in two senses:
a) it returns the image filename WITHOUT the path, so the $qo->image/"Image to display" points to incorrect location (unless image is in root dir)
b) importimagefile fails to CREATE image dir if not exists previously. So, if the teacher is not aware of teh images locations and creates manually the appropriate subdirs BEFORE importing the procedure will fail.
I propose two modifications to importimagefile() to fix these issues:
function importimagefile( $path, $base64 ) {
global $CFG;
// all this to get the destination directory
// and filename!
$fullpath = "{$CFG->dataroot}/{$this->course->id}/$path";
$path_parts = pathinfo( $fullpath );
$destination = $path_parts['dirname'];
$file = clean_filename( $path_parts['basename'] );
//check if path exists <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
check_dir_exists($destination, true, true); // ULPGC ecastro <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// detect and fix any filename collision - get unique filename
$newfiles = resolve_filename_collisions( $destination, array($file) );
print_object("files:");
print_object($newfiles);
$newfile = $newfiles[0];
// convert and save file contents
if (!$content = base64_decode( $base64 ))
$newfullpath = "$destination/$newfile";
if (!$fh = fopen( $newfullpath, 'w' )) { return ''; }
if (!fwrite( $fh, $content ))
{ return ''; }fclose( $fh );
// return the (possibly) new filename
// include the path from course root. // ULPGC ecastro <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$newfile = ereg_replace("{$CFG->dataroot}/{$this->course->id}/", '',$newfullpath); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
return $newfile;
}
The code is the same for all versions from 1.6 to 1.9(HEAD)
Hope this can be fixed rapidly.
Cheers