MDL-29956: Common Cartridge should handle HTML content more natively (r17188, r17210:17265)

Also implemented support for LTI icon during import.
This commit is contained in:
Mark Nielsen
2011-11-14 21:25:08 +01:00
committed by Eloy Lafuente (stronk7)
parent 91e6ca6e71
commit 726a770949
21 changed files with 647 additions and 57 deletions
+10 -2
View File
@@ -63,8 +63,11 @@ class cc112moodle extends cc2moodle {
public function generate_moodle_xml () {
global $CFG;
$cdir = static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files';
mkdir(static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files');
if (!file_exists($cdir)) {
mkdir($cdir);
}
$sheet_base = static::loadsheet(SHEET_BASE);
@@ -175,6 +178,7 @@ class cc112moodle extends cc2moodle {
}
protected function create_node_course_modules_mod () {
$labels = new cc_label();
$resources = new cc11_resource();
$forums = new cc11_forum();
$quiz = new cc11_quiz();
@@ -182,6 +186,9 @@ class cc112moodle extends cc2moodle {
static::log_action('Creating node: COURSE/MODULES/MOD');
// LABELS
$node_course_modules_mod_label = $labels->generate_node();
// RESOURCES (WEB CONTENT AND WEB LINK)
$node_course_modules_mod_resource = $resources->generate_node();
@@ -194,7 +201,8 @@ class cc112moodle extends cc2moodle {
//BasicLTI
$node_course_modules_mod_basiclti = $basiclti->generate_node();
$node_course_modules = $node_course_modules_mod_resource .
$node_course_modules = $node_course_modules_mod_label.
$node_course_modules_mod_resource .
$node_course_modules_mod_forum .
$node_course_modules_mod_quiz .
$node_course_modules_mod_basiclti;
+22 -9
View File
@@ -141,7 +141,11 @@ class cc2moodle {
global $CFG;
mkdir(static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files');
$cdir = static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files';
if (!file_exists($cdir)) {
mkdir($cdir);
}
$sheet_base = static::loadsheet(SHEET_BASE);
@@ -295,7 +299,8 @@ class cc2moodle {
// QUIZ
$node_course_modules_mod_quiz = $quiz->generate_node_course_modules_mod();
$node_course_modules = /*$node_course_modules_mod_label .*/ $node_course_modules_mod_resource . $node_course_modules_mod_forum . $node_course_modules_mod_quiz;
//TODO: label
$node_course_modules = $node_course_modules_mod_label . $node_course_modules_mod_resource . $node_course_modules_mod_forum . $node_course_modules_mod_quiz;
return $node_course_modules;
}
@@ -527,7 +532,8 @@ class cc2moodle {
$forum_mod = $count_forum ? $this->create_mod_info_details_mod(MOODLE_TYPE_FORUM, $forum_instance) : '';
$label_mod = $count_label ? $this->create_mod_info_details_mod(MOODLE_TYPE_LABEL, $label_instance) : '';
return /*$label_mod .*/ $resource_mod . $quiz_mod . $forum_mod;
//TODO: label
return $label_mod . $resource_mod . $quiz_mod . $forum_mod;
}
@@ -552,6 +558,11 @@ class cc2moodle {
for ($i = 1; $i <= $instances_quantity; $i++) {
$user_info = ($instances[$i - 1]['common_cartriedge_type'] == static::CC_TYPE_FORUM) ? 'true' : 'false';
if ($instances[$i - 1]['common_cartriedge_type'] == static::CC_TYPE_EMPTY) {
if ($instances[$i - 1]['deep'] <= ROOT_DEEP ) {
continue;
}
}
$replace_values = array($instances[$i - 1]['instance'],
htmlentities($instances[$i - 1]['title']),
@@ -577,7 +588,7 @@ class cc2moodle {
$array_index++;
if ($item->nodeName == "item") {
if ($item->nodeName == "item") {
$identifierref = $xpath->query('@identifierref', $item);
$identifierref = !empty($identifierref->item(0)->nodeValue) ? $identifierref->item(0)->nodeValue : '';
@@ -587,7 +598,6 @@ class cc2moodle {
$cc_type = $this->get_item_cc_type($identifierref);
$moodle_type = $this->convert_to_moodle_type($cc_type);
}
elseif ($item->nodeName == "resource") {
@@ -615,8 +625,10 @@ class cc2moodle {
static::$instances['index'][$array_index]['resource_indentifier'] = $identifierref;
static::$instances['instances'][$moodle_type][] = array('title' => $title,
'instance' => static::$instances['index'][$array_index]['instance'],
'common_cartriedge_type' => $cc_type , 'resource_indentifier' => $identifierref);
'instance' => static::$instances['index'][$array_index]['instance'],
'common_cartriedge_type' => $cc_type,
'resource_indentifier' => $identifierref,
'deep' => $level);
$more_items = $xpath->query('imscc:item', $item);
@@ -677,9 +689,10 @@ class cc2moodle {
if ($cc_type == static::CC_TYPE_QUESTION_BANK) {
$type = MOODLE_TYPE_QUESTION_BANK;
}
/*if ($cc_type == static::CC_TYPE_EMPTY) {
//TODO: label
if ($cc_type == static::CC_TYPE_EMPTY) {
$type = MOODLE_TYPE_LABEL;
}*/
}
return $type;
}
+1
View File
@@ -38,4 +38,5 @@ require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_converter_forum.php');
require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_converter_url.php');
require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_converter_resource.php');
require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_converter_quiz.php');
require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_converter_page.php');
require_once($CFG->dirroot .'/backup/cc/cc_lib/cc_convert_moodle2.php');
+1
View File
@@ -37,6 +37,7 @@ class cc_converter_lti extends cc_converter {
$rt = new basicltil1_resurce_file();
$contextid = $this->doc->nodeValue('/activity/@contextid');
$title = $this->doc->nodeValue('/activity/lti/name');
$text = $this->doc->nodeValue('/activity/lti/intro');
$rt->set_title($title);
$result = cc_helpers::process_linked_files($text,
$this->manifest,
+59
View File
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package backup-convert
* @subpackage cc-library
* @copyright 2011 Darko Miletic <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once 'cc_converters.php';
require_once 'cc_general.php';
require_once 'cc_page.php';
class cc_converter_page extends cc_converter {
public function __construct(cc_i_item &$item, cc_i_manifest &$manifest, $rootpath, $path){
$this->cc_type = cc_version11::webcontent;
$this->defaultfile = 'page.xml';
$this->defaultname = uniqid().'.html';
parent::__construct($item, $manifest, $rootpath, $path);
}
public function convert($outdir) {
$rt = new page11_resurce_file();
$title = $this->doc->nodeValue('/activity/page/name');
$intro = $this->doc->nodeValue('/activity/page/intro');
$contextid = $this->doc->nodeValue('/activity/@contextid');
$pagecontent = $this->doc->nodeValue('/activity/page/content');
$rt->set_title($title);
$rawname = str_replace(' ', '_', strtolower(trim(clean_param($title, PARAM_FILE))));
if (!empty($rawname)) {
$this->defaultname = $rawname.".html";
}
$result = cc_helpers::process_linked_files( $pagecontent,
$this->manifest,
$this->rootpath,
$contextid,
$outdir,
true);
$rt->set_content($result[0]);
$rt->set_intro($intro);
//store everything
$this->store($rt, $outdir, $title, $result[1]);
return true;
}
}
+11 -8
View File
@@ -117,13 +117,16 @@ abstract class cc_converter {
protected function store(general_cc_file $doc, $outdir, $title, $deps = null) {
$rdir = new cc_resource_location($outdir);
$rtp = $rdir->fullpath(true).$this->defaultname;
$doc->saveTo($rtp);
$resource = new cc_resource($rdir->rootdir(), $this->defaultname, $rdir->dirname(true));
$resource->dependency = empty($deps) ? array() : $deps;
$res = $this->manifest->add_resource($resource, null, $this->cc_type);
$resitem = new cc_item();
$resitem->attach_resource($res[0]);
$resitem->title = $title;
$this->item->add_child_item($resitem);
if ( $doc->saveTo($rtp) ) {
$resource = new cc_resource($rdir->rootdir(), $this->defaultname, $rdir->dirname(true));
$resource->dependency = empty($deps) ? array() : $deps;
$res = $this->manifest->add_resource($resource, null, $this->cc_type);
$resitem = new cc_item();
$resitem->attach_resource($res[0]);
$resitem->title = $title;
$this->item->add_child_item($resitem);
} else {
throw new RuntimeException("Unable to save file {$rtp}!");
}
}
}
+7 -4
View File
@@ -60,10 +60,13 @@ class general_cc_file extends XMLGenericDocument {
$vt = empty($schemaLocation) ? '' : ' ';
$schemaLocation .= $vt.$this->ccnamespaces[$key].' '.$value;
}
$this->append_new_attribute_ns($rootel,
$this->ccnamespaces['xsi'],
'xsi:schemaLocation',
$schemaLocation);
if (!empty($schemaLocation) && isset($this->ccnamespaces['xsi'])) {
$this->append_new_attribute_ns($rootel,
$this->ccnamespaces['xsi'],
'xsi:schemaLocation',
$schemaLocation);
}
$this->root = $rootel;
}
+110
View File
@@ -0,0 +1,110 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package backup-convert
* @copyright 2011 Darko Miletic <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once 'cc_general.php';
class page11_resurce_file extends general_cc_file {
protected $rootns = 'xmlns';
protected $rootname = 'html';
protected $ccnamespaces = array('xmlns' => 'http://www.w3.org/1999/xhtml');
protected $content = null;
protected $title = null;
protected $intro = null;
public function set_content($value) {
$this->content = $value;
}
public function set_title($value) {
$this->title = $value;
}
public function set_intro($value) {
$this->intro = htmlspecialchars(strip_tags($value), ENT_COMPAT, 'UTF-8', false);
}
protected function on_create() {
$impl = new DOMImplementation();
$dtd = $impl->createDocumentType( 'html',
'-//W3C//DTD XHTML 1.0 Strict//EN',
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
$doc = $impl->createDocument($this->ccnamespaces[$this->rootns], null, $dtd);
$doc->formatOutput = true;
$doc->preserveWhiteSpace = true;
$this->doc = $doc;
parent::on_create();
}
public function on_save() {
$rns = $this->ccnamespaces[$this->rootns];
//Add the basic tags
$head = $this->append_new_element_ns($this->root, $rns, 'head');
$this->append_new_attribute_ns($head, $rns, 'profile', 'http://dublincore.org/documents/dc-html/');
//Linking Dublin Core Metadata 1.1
$link_dc = $this->append_new_element_ns($head, $rns, 'link');
$this->append_new_attribute_ns($link_dc, $rns, 'rel', 'schema.DC');
$this->append_new_attribute_ns($link_dc, $rns, 'href', 'http://purl.org/dc/elements/1.1/');
$link_dcterms = $this->append_new_element_ns($head, $rns, 'link');
$this->append_new_attribute_ns($link_dcterms, $rns, 'rel', 'schema.DCTERMS');
$this->append_new_attribute_ns($link_dcterms, $rns, 'href', 'http://purl.org/dc/terms/');
//Content type
$meta_type = $this->append_new_element_ns($head, $rns, 'meta');
$this->append_new_attribute_ns($meta_type, $rns, 'name' , 'DC.type' );
$this->append_new_attribute_ns($meta_type, $rns, 'scheme' , 'DCTERMS.DCMIType');
$this->append_new_attribute_ns($meta_type, $rns, 'content', 'Text' );
//Content description
if (!empty($this->intro)) {
$meta_description = $this->append_new_element_ns($head, $rns , 'meta' );
$this->append_new_attribute_ns($meta_description, $rns, 'name' , 'DC.description');
$this->append_new_attribute_ns($meta_description, $rns, 'content', $this->intro );
}
$meta = $this->append_new_element_ns($head, $rns, 'meta');
$this->append_new_attribute_ns($meta, $rns, 'http-equiv', 'Content-type');
$this->append_new_attribute_ns($meta, $rns, 'content', 'text/html; charset=UTF-8');
//set the title
$title = $this->append_new_element_ns($head, $rns, 'title', $this->title);
$body = $this->append_new_element_ns($this->root, $rns, 'body');
//We are unable to use DOM for embedding HTML due to numerous content errors
//Therefore we place a dummy tag that will be later replaced with the real content
$this->append_new_element_ns($body, $rns, 'div', '##REPLACE##');
return true;
}
public function saveTo($fname) {
$result = $this->on_save();
if ($result) {
$dret = str_replace('<?xml version="1.0"?>'."\n", '', $this->viewXML());
$dret = str_replace('<div>##REPLACE##</div>', $this->content, $dret);
$result = (file_put_contents($fname, $dret) !== false);
if ($result) {
$this->filename = $fname;
$this->processPath();
}
}
return $result;
}
}
+50 -13
View File
@@ -73,6 +73,31 @@ abstract class cc_helpers {
return $dirname;
}
public static function build_query($attributes, $search) {
$result = '';
foreach ($attributes as $attribute) {
if ($result != '') {
$result .= ' | ';
}
$result .= "//*[starts-with(@{$attribute},'{$search}')]/@{$attribute}";
}
return $result;
}
public static function process_embedded_files(&$doc, $attributes, $search, $customslash = null) {
$result = array();
$query = self::build_query($attributes, $search);
$list = $doc->nodeList($query);
foreach ($list as $filelink) {
$rvalue = str_replace($search, '', $filelink->nodeValue);
if (!empty($customslash)) {
$rvalue = str_replace($customslash, '/', $rvalue);
}
$result[] = rawurldecode($rvalue);
}
return $result;
}
/**
*
* Get list of embedded files
@@ -82,12 +107,13 @@ abstract class cc_helpers {
public static function embedded_files($html) {
$result = array();
$doc = new XMLGenericDocument();
$doc->doc->validateOnParse = false;
$doc->doc->strictErrorChecking = false;
if (!empty($html) && $doc->loadHTML($html)) {
$list = $doc->nodeList("//img[starts-with(@src,'@@PLUGINFILE@@')]/@src | //a[starts-with(@href,'@@PLUGINFILE@@')]/@href");
foreach ($list as $filelink) {
$rawvalue = rawurldecode(str_replace('@@PLUGINFILE@@', '', $filelink->nodeValue));
$result[] = $rawvalue;
}
$attributes = array('src', 'href');
$result1 = self::process_embedded_files($doc, $attributes, '@@PLUGINFILE@@');
$result2 = self::process_embedded_files($doc, $attributes, '$@FILEPHP@$', '$@SLASH@$');
$result = array_merge($result1, $result2);
}
return $result;
}
@@ -139,10 +165,10 @@ abstract class cc_helpers {
if (!$allinone) {
$rdir = new cc_resource_location($outdir);
}
$rtp = $rdir->fullpath(true).$clean_filename;
$rtp = $rdir->fullpath().$values[7].$clean_filename;
//Are there any relative virtual directories?
//let us try to recreate them
$justdir = $rdir->fullpath(true).$values[7];
$justdir = $rdir->fullpath(false).$values[7];
if (!file_exists($justdir)) {
if (!mkdir($justdir, 0777, true)) {
throw new RuntimeException('Unable to create directories!');
@@ -153,9 +179,15 @@ abstract class cc_helpers {
if (!copy($source, $rtp)) {
throw new RuntimeException('Unable to copy files!');
}
$resource = new cc_resource($rdir->rootdir(), $clean_filename, $rdir->dirname(true));
$resource = new cc_resource($rdir->rootdir(),
$values[7].$clean_filename,
$rdir->dirname(false));
$res = $manifest->add_resource($resource, null, cc_version11::webcontent);
pkg_static_resources::instance()->add($virtual, $res[0], $rdir->dirname(true).$clean_filename, $values[1], $resource);
pkg_static_resources::instance()->add($virtual,
$res[0],
$rdir->dirname(false).$values[7].$clean_filename,
$values[1],
$resource);
}
pkg_static_resources::instance()->finished = true;
@@ -214,7 +246,7 @@ abstract class cc_helpers {
return $result;
}
public static function process_linked_files($content, cc_i_manifest &$manifest, $packageroot, $contextid, $outdir) {
public static function process_linked_files($content, cc_i_manifest &$manifest, $packageroot, $contextid, $outdir, $webcontent = false) {
/**
- detect all embedded files
- locate their physical counterparts in moodle 2 backup
@@ -233,11 +265,16 @@ abstract class cc_helpers {
$packageroot,
$contextid,
$outdir);
$replaceprefix = $webcontent ? '' : '$IMS-CC-FILEBASE$';
foreach ($lfiles as $lfile) {
if (array_key_exists($lfile, $files)) {
$filename = rawurlencode(basename($lfile));
$content = str_replace('@@PLUGINFILE@@/'.$filename,
'$IMS-CC-FILEBASE$../'.$files[$lfile][1],
$filename = str_replace('%2F', '/',rawurlencode($lfile));
$content = str_replace('@@PLUGINFILE@@'.$filename,
$replaceprefix.'../'.$files[$lfile][1],
$content);
//for the legacy stuff
$content = str_replace('$@FILEPHP@$'.str_replace('/','$@SLASH@$',$filename),
$replaceprefix.'../'.$files[$lfile][1],
$content);
$deps[] = $files[$lfile][0];
}
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
require_once $CFG->dirroot .'/backup/cc/cc_lib/xmlbase.php';
require_once dirname(__FILE__) .'/../xmlbase.php';
require_once 'cssparser.php';
require_once 'pathutils.php';
+3 -3
View File
@@ -34,7 +34,7 @@ class XMLGenericDocument {
* @var DOMXPath
*/
protected $dxpath = null;
private $filename;
protected $filename;
private $filepath;
private $isloaded = false;
private $arrayPrefixNS = array();
@@ -74,7 +74,7 @@ class XMLGenericDocument {
}
public function viewXML (){
return $this->doc->saveXML;
return $this->doc->saveXML();
}
public function registerNS($prefix, $nsuri) {
@@ -402,7 +402,7 @@ class XMLGenericDocument {
}
}
private function processPath(){
protected function processPath(){
$path_parts = pathinfo($this->filename);
$this->filepath = array_key_exists('dirname',$path_parts) ? $path_parts['dirname']."/" : '';
}
+59 -3
View File
@@ -25,6 +25,38 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.');
class entities {
protected function prepare_content($content) {
$result = $content;
if (empty($result)) {
return '';
}
$encoding = null;
$dom = new DOMDocument();
try {
if ($dom->loadHTML($content)) {
$encoding = $dom->xmlEncoding;
}
} catch(DOMException $e) {
//silence the exception if any
}
if (empty($encoding)) {
$encoding = mb_detect_encoding($content, 'auto', true);
}
if (!empty($encoding) && !mb_check_encoding($content, 'UTF-8')) {
$result = mb_convert_encoding($content, 'UTF-8', $encoding);
}
// See if we can strip off body tag and anything outside of it
foreach (array('body', 'html') as $tagname) {
$regex = str_replace('##', $tagname, "/<##[^>]*>(.+)<\/##>/is");
if (preg_match($regex, $result, $matches)) {
$result = $matches[1];
break;
}
}
return $result;
}
public function load_xml_resource ($path_to_file) {
$resource = new DOMDocument();
@@ -173,13 +205,14 @@ class entities {
cc2moodle::log_action('Copy the file: ' . $source . ' to ' . $destination);
//echo 'Copy the file: ' . $source . ' to ' . $destination . '<br>';
if (!file_exists($destination_directory)) {
mkdir($destination_directory, $CFG->directorypermissions, true);
}
$copy_success = @copy($source, $destination);
$copy_success = true;
if (is_file($source)) {
$copy_success = @copy($source, $destination);
}
if (!$copy_success) {
notify('WARNING: Cannot copy the file ' . $source . ' to ' . $destination);
@@ -201,6 +234,11 @@ class entities {
if (!empty($files) && ($files->length > 0)) {
foreach ($files as $file) {
//omit html files
$ext = strtolower(pathinfo($file->nodeValue, PATHINFO_EXTENSION));
if (in_array($ext, array('html', 'htm', 'xhtml'))) {
continue;
}
$all_files[] = $file;
}
}
@@ -208,6 +246,24 @@ class entities {
unset($files);
}
//are there any labels?
$xquery = "//imscc:item/imscc:item/imscc:item[imscc:title][not(@identifierref)]";
$labels = $xpath->query($xquery);
if (!empty($labels) && ($labels->length > 0)) {
$tname = 'course_files';
$dpath = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $tname;
$fpath = $dpath . DIRECTORY_SEPARATOR . 'folder.gif';
$rfpath = $tname.'/folder.gif';
if (!file_exists($dpath)) {
mkdir($dpath);
}
//copy the folder.gif file
$folder_gif = "{$CFG->dirroot}/pix/f/folder.gif";
copy($folder_gif, $fpath);
$all_files[] = $rfpath;
}
$all_files = empty($all_files) ? '' : $all_files;
return $all_files;
+23
View File
@@ -35,6 +35,7 @@ class entities11 extends entities {
}
protected function get_all_files () {
global $CFG;
$all_files = array();
$xpath = cc2moodle::newx_path(cc112moodle::$manifest, cc112moodle::$namespaces);
foreach (cc112moodle::$restypes as $type) {
@@ -44,11 +45,33 @@ class entities11 extends entities {
continue;
}
foreach ($files as $file) {
//omit html files
//this is a bit too simplistic
$ext = strtolower(pathinfo($file->nodeValue, PATHINFO_EXTENSION));
if (in_array($ext, array('html', 'htm', 'xhtml'))) {
continue;
}
$all_files[] = $file;
}
unset($files);
}
//are there any labels?
$xquery = "//imscc:item/imscc:item/imscc:item[imscc:title][not(@identifierref)]";
$labels = $xpath->query($xquery);
if (!empty($labels) && ($labels->length > 0)) {
$tname = 'course_files';
$dpath = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $tname;
$fpath = $dpath . DIRECTORY_SEPARATOR . 'folder.gif';
$rfpath = $tname.'/folder.gif';
if (!file_exists($dpath)) {
mkdir($dpath);
}
//copy the folder.gif file
$folder_gif = "{$CFG->dirroot}/pix/f/folder.gif";
copy($folder_gif, $fpath);
$all_files[] = $rfpath;
}
$all_files = empty($all_files) ? '' : $all_files;
return $all_files;
+8 -3
View File
@@ -42,15 +42,20 @@ class cc_label extends entities {
}
private function create_node_course_modules_mod_label ($sheet_mod_label, $instance) {
if ($instance['deep'] <= ROOT_DEEP) {
return '';
}
$find_tags = array('[#mod_instance#]',
'[#mod_name#]',
'[#mod_content#]',
'[#date_now#]');
//$instance['title']
$title = isset($instance['title']) && !empty($instance['title']) ? $instance['title'] : 'Untitled';
$content = "<img src=\"$@FILEPHP@$$@SLASH@$"."folder.gif\" alt=\"Folder\" title=\"{$title}\" /> {$title}";
$replace_values = array($instance['instance'],
'Untitled',
'Untitled',
$title,
htmlentities($content),
time());
return str_replace($find_tags, $replace_values, $sheet_mod_label);
+69 -4
View File
@@ -45,6 +45,8 @@ class cc_resource extends entities {
private function create_node_course_modules_mod_resource ($sheet_mod_resource, $instance) {
$link = '';
$mod_alltext = '';
$mod_summary = '';
$xpath = cc2moodle::newx_path(cc2moodle::$manifest, cc2moodle::$namespaces);
if ($instance['common_cartriedge_type'] == cc2moodle::CC_TYPE_WEBCONTENT || $instance['common_cartriedge_type'] == cc2moodle::CC_TYPE_ASSOCIATED_CONTENT) {
@@ -89,16 +91,79 @@ class cc_resource extends entities {
'[#mod_reference#]',
'[#mod_summary#]',
'[#mod_alltext#]',
'[#mod_options#]',
'[#date_now#]');
$mod_type = 'file';
$mod_options = 'objectframe';
$mod_reference = $link;
//detected if we are dealing with html file
if (!empty($link) && ($instance['common_cartriedge_type'] == cc112moodle::CC_TYPE_WEBCONTENT)) {
$ext = strtolower(pathinfo($link, PATHINFO_EXTENSION));
if (in_array($ext, array('html', 'htm', 'xhtml'))) {
$mod_type = 'html';
//extract the content of the file
$rootpath = realpath(cc112moodle::$path_to_manifest_folder);
$htmlpath = realpath($rootpath . DIRECTORY_SEPARATOR . $link);
$dirpath = dirname($htmlpath);
if (file_exists($htmlpath)) {
$fcontent = file_get_contents($htmlpath);
$mod_alltext = clean_param($this->prepare_content($fcontent), PARAM_CLEANHTML);
$mod_reference = '';
$mod_options = '';
//TODO: try to handle embedded resources
/**
* images, linked static resources, applets, videos
*/
$doc = new DOMDocument();
$cdir = getcwd();
chdir($dirpath);
try {
$doc->loadHTML($mod_alltext);
$xpath = new DOMXPath($doc);
$attributes = array('href', 'src', 'background', 'archive', 'code');
$qtemplate = "//*[@##][not(contains(@##,'://'))]/@##";
$query = '';
foreach ($attributes as $attrname) {
if (!empty($query)) {
$query .= " | ";
}
$query .= str_replace('##', $attrname, $qtemplate);
}
$list = $xpath->query($query);
$searches = array();
$replaces = array();
foreach ($list as $resrc) {
$rpath = $resrc->nodeValue;
$rtp = realpath($rpath);
if (($rtp !== false) && is_file($rtp)) {
//file is there - we are in business
$strip = str_replace("\\", "/", str_ireplace($rootpath, '', $rtp));
$encoded_file = '$@FILEPHP@$'.str_replace('/', '$@SLASH@$', $strip);
$searches[] = $resrc->nodeValue;
$replaces[] = $encoded_file;
}
}
$mod_alltext = str_replace($searches, $replaces, $mod_alltext);
} catch (Exception $e) {
//silence the complaints
}
chdir($cdir);
$mod_alltext = htmlspecialchars($mod_alltext, ENT_COMPAT, 'UTF-8', false);
}
}
}
$replace_values = array($instance['instance'],
htmlentities($instance['title']),
'file',
htmlentities($link),
'',
htmlspecialchars($instance['title']),
$mod_type,
$mod_reference,
'',
$mod_alltext,
$mod_options,
time());
return str_replace($find_tags, $replace_values, $sheet_mod_resource);
}
}
+6 -2
View File
@@ -53,14 +53,16 @@ class cc11_lti extends entities11 {
'[#mod_basiclti_intro#]' ,
'[#mod_basiclti_timec#]' ,
'[#mod_basiclti_timem#]' ,
'[#mod_basiclti_toolurl#]'
'[#mod_basiclti_toolurl#]',
'[#mod_basiclti_icon#]'
);
$replace_values = array($instance['instance'],
$topic_data['title'],
$topic_data['description'],
time(),time(),
$topic_data['launchurl']
$topic_data['launchurl'],
$topic_data['icon']
);
$result = str_replace($find_tags, $replace_values, $sheet_mod_basiclti);
@@ -93,12 +95,14 @@ class cc11_lti extends entities11 {
$topic_title = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:title'),'Untitled');
$blti_description = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:description'));
$launch_url = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:launch_url'));
$launch_icon = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:icon'));
$tool_raw = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:vendor/lticp:code'),null);
$tool_url = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:vendor/lticp:url'),null);
$tool_desc = $this->getValue($xpath->query('/xmlns:cartridge_basiclti_link/blti:vendor/lticp:description'),null);
$topic_data['title' ] = $topic_title;
$topic_data['description'] = $blti_description;
$topic_data['launchurl' ] = $launch_url;
$topic_data['icon' ] = $launch_icon;
$topic_data['orgid' ] = $tool_raw;
$topic_data['orgurl' ] = $tool_url;
$topic_data['orgdesc' ] = $tool_desc;
+68 -4
View File
@@ -45,6 +45,8 @@ class cc11_resource extends entities11 {
private function create_node_course_modules_mod_resource ($sheet_mod_resource, $instance) {
$link = '';
$mod_alltext = '';
$mod_summary = '';
$xpath = cc112moodle::newx_path(cc112moodle::$manifest, cc112moodle::$namespaces);
if ($instance['common_cartriedge_type'] == cc112moodle::CC_TYPE_WEBCONTENT || $instance['common_cartriedge_type'] == cc112moodle::CC_TYPE_ASSOCIATED_CONTENT) {
@@ -97,14 +99,76 @@ class cc11_resource extends entities11 {
'[#mod_reference#]',
'[#mod_summary#]',
'[#mod_alltext#]',
'[#mod_options#]',
'[#date_now#]');
$mod_type = 'file';
$mod_options = 'objectframe';
$mod_reference = $link;
//detected if we are dealing with html file
if (!empty($link) && ($instance['common_cartriedge_type'] == cc112moodle::CC_TYPE_WEBCONTENT)) {
$ext = strtolower(pathinfo($link, PATHINFO_EXTENSION));
if (in_array($ext, array('html', 'htm', 'xhtml'))) {
$mod_type = 'html';
//extract the content of the file
$rootpath = realpath(cc112moodle::$path_to_manifest_folder);
$htmlpath = realpath($rootpath . DIRECTORY_SEPARATOR . $link);
$dirpath = dirname($htmlpath);
if (file_exists($htmlpath)) {
$fcontent = file_get_contents($htmlpath);
$mod_alltext = clean_param($this->prepare_content($fcontent), PARAM_CLEANHTML);
$mod_reference = '';
$mod_options = '';
/**
* try to handle embedded resources
* images, linked static resources, applets, videos
*/
$doc = new DOMDocument();
$cdir = getcwd();
chdir($dirpath);
try {
$doc->loadHTML($mod_alltext);
$xpath = new DOMXPath($doc);
$attributes = array('href', 'src', 'background', 'archive', 'code');
$qtemplate = "//*[@##][not(contains(@##,'://'))]/@##";
$query = '';
foreach ($attributes as $attrname) {
if (!empty($query)) {
$query .= " | ";
}
$query .= str_replace('##', $attrname, $qtemplate);
}
$list = $xpath->query($query);
$searches = array();
$replaces = array();
foreach ($list as $resrc) {
$rpath = $resrc->nodeValue;
$rtp = realpath($rpath);
if (($rtp !== false) && is_file($rtp)) {
//file is there - we are in business
$strip = str_replace("\\", "/", str_ireplace($rootpath, '', $rtp));
$encoded_file = '$@FILEPHP@$'.str_replace('/', '$@SLASH@$', $strip);
$searches[] = $resrc->nodeValue;
$replaces[] = $encoded_file;
}
}
$mod_alltext = str_replace($searches, $replaces, $mod_alltext);
} catch (Exception $e) {
//silence the complaints
}
chdir($cdir);
$mod_alltext = htmlspecialchars($mod_alltext, ENT_COMPAT, 'UTF-8', false);
}
}
}
$replace_values = array($instance['instance'],
htmlentities($instance['title']),
'file',
htmlentities($link),
'',
htmlspecialchars($instance['title']),
$mod_type,
$mod_reference,
'',
$mod_alltext,
$mod_options,
time());
return str_replace($find_tags, $replace_values, $sheet_mod_resource);
@@ -15,4 +15,5 @@
<INSTRUCTORCHOICEALLOWSETTING>$@NULL@$</INSTRUCTORCHOICEALLOWSETTING>
<GRADE>100.00000</GRADE>
<INSTRUCTORCUSTOMPARAMETERS>0</INSTRUCTORCUSTOMPARAMETERS>
<ICON>[#mod_basiclti_icon#]</ICON>
</MOD>
@@ -7,6 +7,6 @@
<SUMMARY>[#mod_summary#]</SUMMARY>
<ALLTEXT>[#mod_alltext#]</ALLTEXT>
<POPUP></POPUP>
<OPTIONS>objectframe</OPTIONS>
<OPTIONS>[#mod_options#]</OPTIONS>
<TIMEMODIFIED>[#date_now#]</TIMEMODIFIED>
</MOD>
+13
View File
@@ -0,0 +1,13 @@
<?php
require_once($CFG->dirroot . '/backup/converter/convertlib.php');
class imscc1_export_converter extends base_converter {
public static function is_available() {
return false;
}
protected function execute() {
}
}
+124
View File
@@ -0,0 +1,124 @@
<?php
/**
* Provides Common Cartridge v1 converter class
*
* @package core
* @subpackage backup-convert
* @copyright 2011 Darko Miletic <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/backup/converter/convertlib.php');
require_once($CFG->dirroot . '/backup/cc/includes/constants.php');
require_once($CFG->dirroot . '/backup/cc/cc2moodle.php');
require_once($CFG->dirroot . '/backup/cc/validator.php');
class imscc1_converter extends base_converter {
/**
* Log a message
*
* @see parent::log()
* @param string $message message text
* @param int $level message level {@example backup::LOG_WARNING}
* @param null|mixed $a additional information
* @param null|int $depth the message depth
* @param bool $display whether the message should be sent to the output, too
*/
public function log($message, $level, $a = null, $depth = null, $display = false) {
parent::log('(imscc1) '.$message, $level, $a, $depth, $display);
}
/**
* Detects the Common Cartridge 1.0 format of the backup directory
*
* @param string $tempdir the name of the backup directory
* @return null|string backup::FORMAT_IMSCC1 if the Common Cartridge 1.0 is detected, null otherwise
*/
public static function detect_format($tempdir) {
global $CFG;
$filepath = $CFG->dataroot . '/temp/backup/' . $tempdir;
$manifest = cc2moodle::get_manifest($filepath);
if (!empty($manifest)) {
// looks promising, lets load some information
$handle = fopen($manifest, 'r');
$xml_snippet = fread($handle, 500);
fclose($handle);
// check if it has the required strings
$xml_snippet = strtolower($xml_snippet);
$xml_snippet = preg_replace('/\s*/m', '', $xml_snippet);
$xml_snippet = str_replace("'", '', $xml_snippet);
$xml_snippet = str_replace('"', '', $xml_snippet);
$search_string = "xmlns=http://www.imsglobal.org/xsd/imscc/imscp_v1p1";
if (strpos($xml_snippet, $search_string) !== false) {
return backup::FORMAT_IMSCC1;
}
}
return null;
}
/**
* Returns the basic information about the converter
*
* The returned array must contain the following keys:
* 'from' - the supported source format, eg. backup::FORMAT_MOODLE1
* 'to' - the supported target format, eg. backup::FORMAT_MOODLE
* 'cost' - the cost of the conversion, non-negative non-zero integer
*/
public static function description() {
return array(
'from' => backup::FORMAT_IMSCC1,
'to' => backup::FORMAT_MOODLE1,
'cost' => 10
);
}
protected function execute() {
global $CFG;
$manifest = cc2moodle::get_manifest($this->get_tempdir_path());
if (empty($manifest)) {
throw new imscc1_convert_exception('No Manifest detected!');
}
$this->log('validating manifest', backup::LOG_DEBUG, null, 1);
$validator = new manifest10_validator($CFG->dirroot . '/backup/cc/schemas');
if (!$validator->validate($manifest)) {
$this->log('validation error(s): '.PHP_EOL.error_messages::instance(), backup::LOG_DEBUG, null, 2);
throw new imscc1_convert_exception(error_messages::instance()->to_string(true));
}
$manifestdir = dirname($manifest);
$cc2moodle = new cc2moodle($manifest);
if ($cc2moodle->is_auth()) {
throw new imscc1_convert_exception('Protected cartridge content - Skipping import!');
}
$status = $cc2moodle->generate_moodle_xml();
//Final cleanup
$mdoc = new DOMDocument();
$mdoc->preserveWhiteSpace = false;
$mdoc->formatOutput = true;
$mdoc->validateOnParse = false;
if ($mdoc->load($manifestdir.'/moodle.xml', LIBXML_NONET)) {
$mdoc->save($this->get_workdir_path().'/moodle.xml', LIBXML_NOEMPTYTAG);
}
//Move the files to the workdir
rename($manifestdir.'/course_files', $this->get_workdir_path().'/course_files');
}
}
/**
* Exception thrown by this converter
*/
class imscc1_convert_exception extends convert_exception {
}