Add "arrange content".
authorCindy Li <cli@ocad.ca>
Thu, 3 Jun 2010 16:05:23 +0000 (16:05 -0000)
committerCindy Li <cli@ocad.ca>
Thu, 3 Jun 2010 16:05:23 +0000 (16:05 -0000)
More progress on "import/export content" in a course

36 files changed:
docs/home/classes/ContentManager.class.php
docs/home/classes/ContentUtility.class.php
docs/home/course/content.php
docs/home/editor/arrange_content.php
docs/home/editor/edit_content.php
docs/home/editor/edit_content_folder.php
docs/home/editor/import_export_content.php [new file with mode: 0644]
docs/home/ims/ims_export.php
docs/home/ims/ims_import.php
docs/home/ims/include/adlcp_rootv1p2.xsd [new file with mode: 0644]
docs/home/ims/include/footer.html [new file with mode: 0644]
docs/home/ims/include/ims.css [new file with mode: 0644]
docs/home/ims/include/ims_template.inc.php [new file with mode: 0644]
docs/home/ims/include/ims_xml.xsd [new file with mode: 0644]
docs/home/ims/include/imscp_rootv1p1p2.xsd [new file with mode: 0644]
docs/home/ims/include/imsmd_rootv1p2p1.xsd [new file with mode: 0644]
docs/home/imscc/ims_export.php
docs/images/after.gif [new file with mode: 0644]
docs/images/before.gif [new file with mode: 0644]
docs/images/child_of.gif [new file with mode: 0644]
docs/include/classes/DAO/ContentForumsAssocDAO.class.php
docs/include/classes/DAO/CoursesDAO.class.php
docs/include/classes/DAO/ForumsCoursesDAO.class.php [new file with mode: 0644]
docs/include/classes/DAO/ForumsDAO.class.php [new file with mode: 0644]
docs/include/classes/DiscussionTools/DiscussionTools.class.php [new file with mode: 0644]
docs/include/classes/DiscussionTools/DiscussionToolsImport.class.php [new file with mode: 0644]
docs/include/classes/DiscussionTools/DiscussionToolsParser.class.php [new file with mode: 0644]
docs/include/imscc/ims_template.inc.php
docs/include/page_constants.inc.php
docs/install/db/db_schema.sql
docs/install/db/language_text_temp.sql
docs/themes/default/home/course/content.tmpl.php
docs/themes/default/home/editor/arrange_content.tmpl.php [new file with mode: 0644]
docs/themes/default/images/Thumbs.db
docs/themes/default/images/arrange_content.gif [new file with mode: 0644]
docs/themes/default/include/header.tmpl.php

index 87aaa72..c2fb7dd 100644 (file)
@@ -280,7 +280,7 @@ class ContentManager
 //             $result = mysql_query($sql, $this->db);
 //             $row = mysql_fetch_assoc($result);
                $row = $this->contentDAO->execute($sql);
-               $max_ordering = $row['max_ordering'];
+               $max_ordering = $row[0]['max_ordering'];
                
                if ($content_id == $new_content_parent_id) {
                        $msg->addError("NO_SELF_AS_PARENT");
@@ -305,7 +305,6 @@ class ContentManager
                // to the last element under the same parent content.
                if ($old_content_parent_id == $new_content_parent_id && $new_content_ordering > $max_ordering) 
                        $new_content_ordering = $max_ordering;
-               
                if (($old_content_parent_id != $new_content_parent_id) || ($old_ordering != $new_content_ordering)) {
                        // remove the gap left by the moved content
                        $sql = "UPDATE ".TABLE_PREFIX."content 
index d5289e6..8244998 100644 (file)
@@ -567,7 +567,7 @@ class ContentUtility {
        }\r
        \r
        /**\r
-        * This function returns html string of "table of content"\r
+        * This function returns an array of content tools' shortcuts\r
         * @access: public\r
         * @param: $content_row: an array of the current content information\r
         * @return: an array of all the tool short cuts that apply to the current content or content folder\r
index 39e2162..3bd205c 100644 (file)
@@ -13,6 +13,7 @@
 define('TR_INCLUDE_PATH', '../../include/');
 require_once(TR_INCLUDE_PATH.'vitals.inc.php');
 require_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php');
+require_once(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php');
 
 global $_current_user, $_course_id, $_content_id, $contentManager;
 
@@ -125,7 +126,7 @@ $_pages['home/course/content.php'] = $last_page;
 reset($path);
 $first_page = current($path);
 
-/* the content test extension page */
+/* the tests associated with the content */
 $content_test_ids = array();   //the html
 $content_test_rows = $contentManager->getContentTestsAssoc($cid);
 if (is_array($content_test_rows))
@@ -135,6 +136,17 @@ if (is_array($content_test_rows))
        }
 }
 
+/* the forums associated with the content */
+$contentForumsAssocDAO = new ContentForumsAssocDAO();
+$content_forum_ids = $contentForumsAssocDAO->getByContent($cid);
+//$content_test_rows = $contentManager->getContentTestsAssoc($cid);
+//if (is_array($content_test_rows))
+//{
+//     foreach ($content_test_rows as $content_test_row){
+//             $content_test_ids[] = $content_test_row;
+//     }
+//}
+
 /*TODO***************BOLOGNA***************REMOVE ME**********/
 /* the content forums extension page*/
 //$content_forum_ids = array();        //the html
@@ -270,16 +282,10 @@ if ($content_row['text'] == '' && empty($content_test_ids)){
                $savant->assign('test_message', '');
                $savant->assign('test_ids', array());
        }
-
-               /*TODO***************BOLOGNA***************REMOVE ME**********/
-               //assign forum pages if there are forums associated with this content page
-//             if (!empty($content_forum_ids)){
-//                     $savant->assign('forum_message','');
-//                     $savant->assign('forum_ids', $content_forum_ids);
-//             } else {
-//                     $savant->assign('forum_message', '');
-//                     $savant->assign('forum_ids', array());
-//             }
+       
+       if (is_array($content_forum_ids)){
+               $savant->assign('forum_ids', $content_forum_ids);
+       }
 }
 
 $savant->assign('content_info', _AT('page_info', AT_date(_AT('page_info_date_format'), $content_row['last_modified'], TR_DATE_MYSQL_DATETIME), $content_row['revision'], AT_date(_AT('inbox_date_format'), $content_row['release_date'], TR_DATE_MYSQL_DATETIME)));
index d4a187e..ddfc1eb 100644 (file)
 
 define('TR_INCLUDE_PATH', '../../include/');
 require (TR_INCLUDE_PATH.'vitals.inc.php');
-authenticate(TR_PRIV_CONTENT);
+
+global $_course_id, $contentManager;
+
+Utility::authenticate(TR_PRIV_ISAUTHOR);
 
 if (isset($_POST['move']) && isset($_POST['moved_cid'])) {
        $arr = explode('_', key($_POST['move']), 2);
        $new_pid = $arr[0];
        $new_ordering = $arr[1];
-       
+
        $contentManager->moveContent($_POST['moved_cid'], $new_pid, $new_ordering);
-       header('Location: '.TR_BASE_HREF.'home/editor/arrange_content.php');
+       header('Location: '.TR_BASE_HREF.'home/editor/arrange_content.php?_course_id='.$_course_id);
        exit;
 }
        
 if (!defined('TR_INCLUDE_PATH')) { exit; }
 
 $savant->assign('languageManager', $languageManager);
+$savant->assign('course_id', $_course_id);
 
-$savant->display('editor/arrange_content.tmpl.php');
+$savant->display('home/editor/arrange_content.tmpl.php');
 
 ?>
index c4375d6..657d407 100644 (file)
@@ -12,7 +12,7 @@
 
 define('TR_INCLUDE_PATH', '../../include/');
 
-global $db, $associated_forum, $_course_id, $_content_id;
+global $associated_forum, $_course_id, $_content_id;
 
 require(TR_INCLUDE_PATH.'vitals.inc.php');
 require_once(TR_INCLUDE_PATH.'lib/tinymce.inc.php');
index ad1037b..26159fc 100644 (file)
@@ -15,13 +15,19 @@ require_once(TR_INCLUDE_PATH.'vitals.inc.php');
 require_once(TR_INCLUDE_PATH.'../home/editor/editor_tab_functions.inc.php');
 require_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php');
 
-global $_content_id, $_content_id, $contentManager;
+global $_content_id, $_content_id, $contentManager, $_course_id;
 $cid = $_content_id;
 
 Utility::authenticate(TR_PRIV_ISAUTHOR);
 
 if (isset($_GET['pid'])) $pid = intval($_GET['pid']);
 
+if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) {
+       $course_base_href = 'get.php/';
+} else {
+       $course_base_href = 'content/' . $_course_id . '/';
+}
+
 if ($cid > 0 && isset($contentManager)) {
        $content_row = $contentManager->getContentPage($cid);
 }
@@ -190,4 +196,5 @@ require(TR_INCLUDE_PATH.'footer.inc.php');
 
 //save last visit page.
 $_SESSION['last_visited_page'] = $server_protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+debug($_SESSION['course_id']);
 ?>
\ No newline at end of file
diff --git a/docs/home/editor/import_export_content.php b/docs/home/editor/import_export_content.php
new file mode 100644 (file)
index 0000000..556e5dd
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+define('TR_INCLUDE_PATH', '../../include/');
+require_once(TR_INCLUDE_PATH.'vitals.inc.php');
+
+global $_course_id, $_content_id;
+
+Utility::authenticate(TR_PRIV_ISAUTHOR);
+
+require(TR_INCLUDE_PATH.'header.inc.php');
+if (!isset($_main_menu)) {
+       $_main_menu = $contentManager->getContent();
+}
+
+function print_menu_sections(&$menu, $only_print_content_folder = false, $parent_content_id = 0, $depth = 0, $ordering = '') {
+       $my_children = $menu[$parent_content_id];
+       $cid = $_GET['cid'];
+
+       if (!is_array($my_children)) {
+               return;
+       }
+       foreach ($my_children as $children) {
+               /* test content association, we don't want to display the test pages
+                * as part of the menu section.  If test, skip it.
+                */
+               if (isset($children['test_id'])){
+                       continue;
+               }
+               if ($only_print_content_folder && $children['content_type'] != CONTENT_TYPE_FOLDER) {
+                       continue;
+               }
+
+               echo '<option value="'.$children['content_id'].'"';
+               if ($cid == $children['content_id']) {
+                       echo ' selected="selected"';
+               }
+               echo '>';
+               echo str_pad('', $depth, '-') . ' ';
+               if ($parent_content_id == 0) {
+                       $new_ordering = $children['ordering'];
+                       echo $children['ordering'];
+               } else {
+                       $new_ordering = $ordering.'.'.$children['ordering'];
+                       echo $ordering . '.'. $children['ordering'];
+               }
+               echo ' '.$children['title'].'</option>';
+
+               print_menu_sections($menu, $only_print_content_folder, $children['content_id'], $depth+1, $new_ordering);
+       }
+}
+
+//if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'none')) {
+//     echo '<p>'._AT('content_packaging_disabled').'</p>';
+//     require (AT_INCLUDE_PATH.'footer.inc.php'); 
+//     exit;
+//} else if (!authenticate(AT_PRIV_CONTENT, AT_PRIV_RETURN) && ($_SESSION['packaging'] == 'top')) {
+//     $_main_menu = array($_main_menu[0]);
+//}
+?>
+<form name="exportForm" method="post" action="home/ims/ims_export.php">
+<div class="input-form">
+       <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" />
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('export_content'); ?></legend>
+       <div class="row">
+               <p><?php echo _AT('export_content_info'); ?></p>
+       </div>
+
+<?php if ($_main_menu[0]): ?>
+       <div class="row">
+               <label for="select_cid"><?php echo _AT('export_content_package_what'); ?></label><br />
+               <select name="cid" id="select_cid">
+                       <option value="0"><?php echo _AT('export_entire_course_or_chap'); ?></option>
+                       <option value="0"></option>
+                       <?php
+                               print_menu_sections($_main_menu);
+                       ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="radio" name="export_as" id="to_cp" value="1" checked="checked" onclick="changeFormAction('cp');" />
+               <label for="to_cp"><?php echo _AT('content_package'); ?></label> <br />
+               <input type="radio" name="export_as" id="to_cc" value="1" onclick="changeFormAction('cc');" />
+               <label for="to_cc"><?php echo _AT('common_cartridge'); ?> </label>
+       </div>
+       <div class="row">
+               <input type="checkbox" name="to_a4a" id="to_a4a" value="1" />
+               <label for="to_a4a"><?php echo _AT('a4a_export'); ?></label>
+       </div>
+       
+       <div class="row buttons">
+               <input type="submit" name="submit" value="<?php echo _AT('export'); ?>" />
+               <input type="submit" name="cancel" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+       </fieldset>
+<?php else: ?>
+       <div class="row">
+               <strong><?php echo _AT('none_found'); ?></strong>
+       </div>
+<?php endif; ?>
+
+</div>
+</form>
+
+<form name="form1" method="post" action="home/imscp/ims_import.php" enctype="multipart/form-data" onsubmit="openWindow('<?php echo AT_BASE_HREF; ?>tools/prog.php');">
+<div class="input-form">
+       <input type="hidden" name="_course_id" value="<?php echo $_course_id; ?>" />
+       <fieldset class="group_form"><legend class="group_form"><?php echo _AT('import_content'); ?></legend>
+       <div class="row">
+
+               <p><?php echo _AT('import_content_info'); ?></p>
+       </div>
+
+       <div class="row">
+               <label for="select_cid2"><?php echo _AT('import_content_package_where'); ?></label><br />
+               <select name="cid" id="select_cid2">
+                       <option value="0"><?php echo _AT('import_content_package_bottom_subcontent'); ?></option>
+                       <option value="0"></option>
+                       <?php
+                               print_menu_sections($_main_menu, true);
+                       ?>
+               </select>
+       </div>
+
+       <div class="row">
+               <input type="checkbox" name="allow_test_import" id="allow_test_import" checked="checked" />
+               <label for="allow_test_import"><?php echo _AT('test_import_package'); ?></label> <br />
+               <input type="checkbox" name="allow_a4a_import" id="allow_a4a_import" checked="checked" />
+               <label for="allow_a4a_import"><?php echo _AT('a4a_import_package'); ?></label>          
+       </div>
+       
+       <div class="row">
+               <label for="to_file"><?php echo _AT('upload_content_package'); ?></label><br />
+               <input type="file" name="file" id="to_file" />
+       </div>
+
+       <div class="row">
+               <label for="to_url"><?php echo _AT('specify_url_to_content_package'); ?></label><br />
+               <input type="text" name="url" value="http://" size="40" id="to_url" />
+       </div>
+
+       <div class="row buttons">
+               <input type="submit" name="submit" onclick="setClickSource('submit');" value="<?php echo _AT('import'); ?>" />
+               <input type="submit" name="cancel" onclick="document.form1.enctype='';setClickSource('cancel');" value="<?php echo _AT('cancel'); ?>" />
+       </div>
+</div>
+</form>
+
+<script language="javascript" type="text/javascript">
+
+var but_src;
+function setClickSource(name) {
+       but_src = name;
+}
+
+function openWindow(page) {
+       if (but_src != "cancel") {
+               newWindow = window.open(page, "progWin", "width=400,height=200,toolbar=no,location=no");
+               newWindow.focus();
+       }
+}
+
+//Change form action 
+function changeFormAction(type){
+       var obj = document.exportForm;
+       if (type=="cc"){
+               obj.action = "home/imscc/ims_export.php";
+       } else if (type=="cp"){
+               obj.action = "home/ims/ims_export.php";
+       }
+}
+
+</script>
+
+<?php require (TR_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
index 837dc30..fa21243 100644 (file)
 
 define('TR_INCLUDE_PATH', '../../include/');
 
-/* content id of an optional chapter */
-$cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : 0;
-$c   = isset($_REQUEST['c'])   ? intval($_REQUEST['c'])   : 0;
-
 if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
        /* for TILE */
 
@@ -41,7 +37,7 @@ if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
        /* request (hopefully) coming from a TILE server, send the content package */
 
        $_user_location = 'public';
-       require(TR_INCLUDE_PATH.'vitals.inc.php');
+       require_once(TR_INCLUDE_PATH.'vitals.inc.php');
        $m = md5(DB_PASSWORD . 'x' . ADMIN_PASSWORD . 'x' . $_SERVER['SERVER_ADDR'] . 'x' . $cid . 'x' . $c . 'x' . date('Ymd'));
        if (($m != $_GET['m']) || !$c) {
                header('HTTP/1.1 404 Not Found');
@@ -56,23 +52,45 @@ if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
        if (isset($_REQUEST['to_a4a'])){
                $use_a4a = true;
        }
-       require(TR_INCLUDE_PATH.'vitals.inc.php');
-       $course_id = $_SESSION['course_id'];
+       require_once(TR_INCLUDE_PATH.'vitals.inc.php');
+       global $_course_id, $_content_id;
+
+       $course_id = (isset($_REQUEST['course_id']) ? intval($_REQUEST['course_id']) : $_course_id);
+       $cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : $_content_id; /* content id of an optional chapter */
+       $c   = isset($_REQUEST['c'])   ? intval($_REQUEST['c'])   : 0;
 }
+
+if ($course_id == 0 && $cid == 0)
+{
+       $msg->addError('MISSING_COURSE_ID');
+       header('Location: ../index.php');
+       exit;   
+}
+
+require_once(TR_INCLUDE_PATH.'../home/classes/ContentManager.class.php');  /* content management class */
+require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php');
+require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php');
+require_once(TR_INCLUDE_PATH.'classes/DAO/UsersDAO.class.php');
+
 //load the following after vitals is included
 require(TR_INCLUDE_PATH.'classes/testQuestions.class.php');
 require(TR_INCLUDE_PATH.'classes/A4a/A4aExport.class.php');
 
-$instructor_id   = $system_courses[$course_id]['member_id'];
-$course_desc     = htmlspecialchars($system_courses[$course_id]['description'], ENT_QUOTES, 'UTF-8');
-$course_title    = htmlspecialchars($system_courses[$course_id]['title'], ENT_QUOTES, 'UTF-8');
-$course_language = $system_courses[$course_id]['primary_language'];
+$coursesDAO = new CoursesDAO();
+$course_row = $coursesDAO->get($course_id);
+
+$contentManager = new ContentManager($course_id);
+
+$instructor_id   = $course_row['user_id'];
+$course_desc     = htmlspecialchars($course_row['description'], ENT_QUOTES, 'UTF-8');
+$course_title    = htmlspecialchars($course_row['title'], ENT_QUOTES, 'UTF-8');
+$course_language = $course_row['primary_language'];
 
 $courseLanguage =& $languageManager->getLanguage($course_language);
 //If course language cannot be found, use UTF-8 English
 //@author harris, Oct 30,2008
-if ($courseLanguage == null){
-       $courseLanguage =& $languageManager->getLanguage('en');
+if (!isset($courseLanguage) || $courseLanguage == null){
+       $courseLanguage =& $languageManager->getLanguage(DEFAULT_LANGUAGE_CODE);
 }
 
 $course_language_charset = $courseLanguage->getCharacterSet();
@@ -81,8 +99,8 @@ $course_language_code = $courseLanguage->getCode();
 require(TR_INCLUDE_PATH.'classes/zipfile.class.php');                          /* for zipfile */
 require(TR_INCLUDE_PATH.'classes/vcard.php');                                          /* for vcard */
 require(TR_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php');    /* for XML_HTMLSax */
-require(TR_INCLUDE_PATH.'imscc/ims_template.inc.php');                         /* for ims templates + print_organizations() */
-
+debug('a');require(TR_INCLUDE_PATH.'../home/ims/include/ims_template.inc.php');/* for ims templates + print_organizations() */
+debug('a');
 if (isset($_POST['cancel'])) {
        $msg->addFeedback('EXPORT_CANCELLED');
        header('Location: ../index.php');
@@ -165,14 +183,20 @@ $parser = new XML_HTMLSax();
 $parser->set_object($handler);
 $parser->set_element_handler('openHandler','closeHandler');
 
-if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN)) {
-       $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
-} else {
-       $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
-}
-$result = mysql_query($sql, $db);
-while ($row = mysql_fetch_assoc($result)) {
-       if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN) || $contentManager->isReleased($row['content_id']) === TRUE) {
+$contentDAO = new ContentDAO();
+$rows = $contentDAO->getContentByCourseID($course_id);
+
+//if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN)) {
+//     $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
+//} else {
+//     $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
+//}
+//$result = mysql_query($sql, $db);
+//while ($row = mysql_fetch_assoc($result)) {
+//     if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN) || $contentManager->isReleased($row['content_id']) === TRUE) {
+
+if (is_array($rows)) {
+       foreach ($rows as $row) {
                $content[$row['content_parent_id']][] = $row;
                if ($cid == $row['content_id']) {
                        $top_content = $row;
@@ -234,13 +258,16 @@ foreach ($content[0] as $content_box){
 }
 */
 
-/* generate the resources and save the HTML files */
-$used_glossary_terms = array();
 ob_start();
 print_organizations($top_content_parent_id, $content, 0, '', array(), $toc_html);
 $organizations_str = ob_get_contents();
 ob_end_clean();
 
+// Modified by Cindy Qi Li on Jun 3, 2010
+// Transformable does not support glossary
+/* generate the resources and save the HTML files */
+/*
+$used_glossary_terms = array();
 if (count($used_glossary_terms)) {
        $used_glossary_terms = array_unique($used_glossary_terms);
        sort($used_glossary_terms);
@@ -273,6 +300,8 @@ if (count($used_glossary_terms)) {
 } else {
        unset($glossary_xml);
 }
+*/
+// END OF Modified by Cindy Qi Li on Jun 3, 2010
 
 $toc_html = str_replace(array('{TOC}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
                                            array($toc_html, $course_language_charset, $course_language_code),
@@ -289,18 +318,19 @@ $html_mainheader = str_replace(array('{COURSE_TITLE}', '{COURSE_PRIMARY_LANGUAGE
                                                           array($ims_course_title, $course_language_charset, $course_language_code),
                                                           $html_mainheader);
 
-
-
 /* append the Organizations and Resources to the imsmanifest */
 $imsmanifest_xml .= str_replace(       array('{ORGANIZATIONS}',        '{RESOURCES}', '{COURSE_TITLE}'),
                                                                        array($organizations_str,       $resources, $ims_course_title),
                                                                        $ims_template_xml['final']);
 
 /* generate the vcard for the instructor/author */
-$sql = "SELECT first_name, last_name, email, website, login, phone FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
-$result = mysql_query($sql, $db);
+//$sql = "SELECT first_name, last_name, email, website, login, phone FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
+//$result = mysql_query($sql, $db);
+$usersDAO = new UsersDAO();
+$row = $usersDAO->getUserByID($instructor_id);
+                                                                       
 $vcard = new vCard();
-if ($row = mysql_fetch_assoc($result)) {
+if (isset($row)) {
        $vcard->setName($row['last_name'], $row['first_name'], $row['login']);
        $vcard->setEmail($row['email']);
        $vcard->setNote('Originated from an Transformable at '.TR_BASE_HREF.'. See ATutor.ca for additional information.');
@@ -317,17 +347,23 @@ $zipfile->add_file($frame,                         'index.html');
 $zipfile->add_file($toc_html,           'toc.html');
 $zipfile->add_file($imsmanifest_xml, 'imsmanifest.xml');
 $zipfile->add_file($html_mainheader, 'header.html');
+
+// Modified by Cindy Qi Li on Jun 3, 2010
+// Transformable does not support glossary
+/*
 if ($glossary_xml) {
        $zipfile->add_file($glossary_xml,  'glossary.xml');
        $zipfile->add_file($glossary_html, 'glossary.html');
 }
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/adlcp_rootv1p2.xsd'), 'adlcp_rootv1p2.xsd');
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/ims_xml.xsd'), 'ims_xml.xsd');
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/imscp_rootv1p1p2.xsd'), 'imscp_rootv1p1p2.xsd');
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/imsmd_rootv1p2p1.xsd'), 'imsmd_rootv1p2p1.xsd');
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/ims.css'), 'ims.css');
-$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'ims/footer.html'), 'footer.html');
-$zipfile->add_file(file_get_contents('../../images/logo.gif'), 'logo.gif');
+*/
+// END OF Modified by Cindy Qi Li on Jun 3, 2010
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/adlcp_rootv1p2.xsd'), 'adlcp_rootv1p2.xsd');
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/ims_xml.xsd'), 'ims_xml.xsd');
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/imscp_rootv1p1p2.xsd'), 'imscp_rootv1p1p2.xsd');
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/imsmd_rootv1p2p1.xsd'), 'imsmd_rootv1p2p1.xsd');
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/ims.css'), 'ims.css');
+$zipfile->add_file(file_get_contents(TR_INCLUDE_PATH.'../home/ims/include/footer.html'), 'footer.html');
+$zipfile->add_file(file_get_contents('../../images/logo.png'), 'logo.png');
 
 $zipfile->close(); // this is optional, since send_file() closes it anyway
 
index 5996d62..1e8de8d 100644 (file)
@@ -79,8 +79,8 @@ require_once(TR_INCLUDE_PATH.'classes/QTI/QTIImport.class.php');
 require_once(TR_INCLUDE_PATH.'classes/A4a/A4aImport.class.php');
 require(TR_INCLUDE_PATH.'../home/ims/ns.inc.php');     //namespace, no longer needs, delete it after it's stable.
 require_once(TR_INCLUDE_PATH.'classes/Weblinks/WeblinksParser.class.php');
-//require(TR_INCLUDE_PATH.'classes/DiscussionTools/DiscussionToolsParser.class.php');
-//require(TR_INCLUDE_PATH.'classes/DiscussionTools/DiscussionToolsImport.class.php');
+require(TR_INCLUDE_PATH.'classes/DiscussionTools/DiscussionToolsParser.class.php');
+require(TR_INCLUDE_PATH.'classes/DiscussionTools/DiscussionToolsImport.class.php');
 
 // make sure the user has author privilege
 Utility::authenticate(TR_PRIV_ISAUTHOR);
@@ -1279,7 +1279,6 @@ foreach ($items as $item_id => $content_info)
 //                             @unlink(TR_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
                        }
 
-                       /** Commented by Cindy Qi Li on Jan 6, 2010. Ignore discussion tools
                        // overwrite content if this is discussion tool.
                        if ($content_info['type']=='imsdt_xmlv1p0'){
                                $dt_parser = new DiscussionToolsParser();
@@ -1290,7 +1289,6 @@ foreach ($items as $item_id => $content_info)
                                unset($forum_obj);
                                $dt_parser->close();
                        }
-                       */
                } else if ($ext) {
                        /* non text file, and can't embed (example: PDF files) */
                        $content = '<a href="'.$content_info['href'].'">'.$content_info['title'].'</a>';
@@ -1457,7 +1455,6 @@ foreach ($items as $item_id => $content_info)
                $a4a_import->importA4a($items[$item_id]['a4a']);
        }
 
-       /** Commented by Cindy Qi Li on Jan 6, 2010. Ignore discussion tools
        // get the discussion tools (dependent to content)
        if (isset($items[$item_id]['forum']) && !empty($items[$item_id]['forum'])){
                foreach($items[$item_id]['forum'] as $forum_ref => $forum_link){
@@ -1469,11 +1466,11 @@ foreach ($items as $item_id => $content_info)
                                $xml_content = @file_get_contents($import_path . $forum_link);
                                $dt_parser->parse($xml_content);
                                $forum_obj = $dt_parser->getDt();
-                               $dt_import->import($forum_obj, $items[$item_id]['real_content_id']);
+                               $dt_import->import($forum_obj, $items[$item_id]['real_content_id'], $_course_id);
                                $added_dt[$forum_ref] = $dt_import->getFid();                           
                        }
                        //associate the fid and content id
-                       $dt_import->associateForum($items[$item_id]['real_content_id'], $added_dt[$forum_ref]);
+//                     $dt_import->associateForum($items[$item_id]['real_content_id'], $added_dt[$forum_ref]);
                }
        } elseif ($items[$item_id]['type']=='imsdt_xmlv1p0'){
                //optimize this, repeated codes as above
@@ -1482,13 +1479,12 @@ foreach ($items as $item_id => $content_info)
                $xml_content = @file_get_contents($import_path . $content_info['href']);
                $dt_parser->parse($xml_content);
                $forum_obj = $dt_parser->getDt();
-               $dt_import->import($forum_obj, $items[$item_id]['real_content_id']);
+               $dt_import->import($forum_obj, $items[$item_id]['real_content_id'], $_course_id);
                $added_dt[$item_id] = $dt_import->getFid();
 
                //associate the fid and content id
-               $dt_import->associateForum($items[$item_id]['real_content_id'], $added_dt[$item_id]);
+//             $dt_import->associateForum($items[$item_id]['real_content_id'], $added_dt[$item_id]);
        }
-       */
 }
 
 //exit;//harris
diff --git a/docs/home/ims/include/adlcp_rootv1p2.xsd b/docs/home/ims/include/adlcp_rootv1p2.xsd
new file mode 100644 (file)
index 0000000..f930690
--- /dev/null
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!-- filename=adlcp_rootv1p2.xsd -->
+<!-- Conforms to w3c http://www.w3.org/TR/xmlschema-1/ 2000-10-24-->
+
+<xsd:schema xmlns="http://www.adlnet.org/xsd/adlcp_rootv1p2"
+            targetNamespace="http://www.adlnet.org/xsd/adlcp_rootv1p2"
+            xmlns:xml="http://www.w3.org/XML/1998/namespace"
+            xmlns:imscp="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="unqualified"
+            version="ADL Version 1.2">
+
+        <xsd:import namespace="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
+         schemaLocation="imscp_rootv1p1p2.xsd"/>
+
+        <xsd:element name="location" type="locationType"/>
+        <xsd:element name="prerequisites" type="prerequisitesType"/>
+        <xsd:element name="maxtimeallowed" type="maxtimeallowedType"/>
+        <xsd:element name="timelimitaction" type="timelimitactionType"/>
+        <xsd:element name="datafromlms" type="datafromlmsType"/>
+        <xsd:element name="masteryscore" type="masteryscoreType"/>
+
+
+        <xsd:element name="schema" type="newSchemaType"/>
+        <xsd:simpleType name="newSchemaType">
+                <xsd:restriction base="imscp:schemaType">
+                        <xsd:enumeration value="ADL SCORM"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:element name="schemaversion" type="newSchemaversionType"/>
+        <xsd:simpleType name="newSchemaversionType">
+                <xsd:restriction base="imscp:schemaversionType">
+                        <xsd:enumeration value="1.2"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+
+        <xsd:attribute name="scormtype">
+            <xsd:simpleType>
+                <xsd:restriction base="xsd:string">
+                   <xsd:enumeration value="asset"/>
+                   <xsd:enumeration value="sco"/>
+                </xsd:restriction>
+            </xsd:simpleType>
+        </xsd:attribute>
+
+        <xsd:simpleType name="locationType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="2000"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+
+        <xsd:complexType name="prerequisitesType">
+           <xsd:simpleContent>
+              <xsd:extension base="prerequisiteStringType">
+                  <xsd:attributeGroup ref="attr.prerequisitetype"/>
+              </xsd:extension>
+           </xsd:simpleContent>
+        </xsd:complexType>
+
+        <xsd:attributeGroup name="attr.prerequisitetype">
+                <xsd:attribute name="type" use="required">
+                        <xsd:simpleType>
+                                <xsd:restriction base="xsd:string">
+                                   <xsd:enumeration value="aicc_script"/>
+                                </xsd:restriction>
+                        </xsd:simpleType>
+                </xsd:attribute>
+        </xsd:attributeGroup>
+
+        <xsd:simpleType name="maxtimeallowedType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="13"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="timelimitactionType">
+                <xsd:restriction base="stringType">
+                        <xsd:enumeration value="exit,no message"/>
+                        <xsd:enumeration value="exit,message"/>
+                        <xsd:enumeration value="continue,no message"/>
+                        <xsd:enumeration value="continue,message"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="datafromlmsType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="255"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="masteryscoreType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:maxLength value="200"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+        <xsd:simpleType name="stringType">
+                <xsd:restriction base="xsd:string"/>
+        </xsd:simpleType>
+        
+        <xsd:simpleType name="prerequisiteStringType">
+                <xsd:restriction base="xsd:string">
+                   <xsd:maxLength value="200"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+</xsd:schema>
diff --git a/docs/home/ims/include/footer.html b/docs/home/ims/include/footer.html
new file mode 100644 (file)
index 0000000..bdb6043
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="ims.css" />
+       <title>About this Content Package</title>
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+<body class="footerbody"> 
+<table>
+<tr>
+       <td valign="middle" align="left"><a href="http://www.atutor.ca/transformable/" target="_blank"><img src="logo.png" border="0" alt="Transformable - opens in a new window" width="84" height="29" align="left" title="ATutor.ca - opens in a new window" /></a></td>
+       <td><span class="footer"><small>For general help with using the Transformable system see the official <a href="http://atutor.ca/transformable/" title="Transformable Handbook - opens in a new window" target="_blank">Transformable <em>Handbook</em> </a>.</small></span></td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/home/ims/include/ims.css b/docs/home/ims/include/ims.css
new file mode 100644 (file)
index 0000000..ec5cc8c
--- /dev/null
@@ -0,0 +1,38 @@
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+/* header */
+body.headerbody { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #EFEFEF;}
+h3 { font-family: Verdana, Arial, Helvetica, sans-serif; color: #384F89; }
+
+/* table of contents */
+ul { 
+       font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: gray;
+       font-size: small;
+}
+ul a { color:#384F89; }
+ul a:hover { text-decoration:none; }
+ul a:visited { color:black; }
+
+li {
+       margin-left: -10px;
+}
+
+/* body */
+body.contentbody { font-family: Verdana, Arial, Helvetica, sans-serif;}
+
+/* footer */
+body.footerbody { font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #384F89; margin-top: 0px;}
+body.footerbody a { font-family: Verdana, Arial, Helvetica, sans-serif; color: white; }
+body.footerbody a:hover { font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration:none; }
+.footer { font-family: Verdana, Arial, Helvetica, sans-serif; color: white; }
+
diff --git a/docs/home/ims/include/ims_template.inc.php b/docs/home/ims/include/ims_template.inc.php
new file mode 100644 (file)
index 0000000..bc8b8ee
--- /dev/null
@@ -0,0 +1,564 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+if (!defined('TR_INCLUDE_PATH')) { exit; }
+
+// This function gets files from html tag @import
+function get_import_files($text)
+{
+       $text = strtolower($text);
+       $tag = '@import';
+       $files = array();
+       
+       while (strpos(strtolower($text), strtolower($tag)) > 0)
+       {
+               $start_pos      = strpos($text, $tag);
+               if ($start_pos !== false) 
+               {
+                       $text = substr($text, $start_pos);
+                       $start_pos = strlen($tag);
+                       $len = strpos($text, ';') - strlen($tag);
+                       
+                       $file = substr(trim($text), $start_pos, $len);
+                       
+                       // remove these characters from file name: url, (, ), ", '
+                       $file = trim(preg_replace('/(\'|\"|url|\(|\))/', '', $file));
+                       
+                       // strip processed tag
+                       $text = substr($text, $start_pos);
+                       array_push($files, $file);
+               }
+       
+       }
+       
+       return $files;
+}
+       
+function print_organizations($parent_id,
+                                                        &$_menu, 
+                                                        $depth, 
+                                                        $path='',
+                                                        $children,
+                                                        &$string) {
+       
+       global $html_content_template, $default_html_style, $zipfile, $resources, $ims_template_xml, $parser, $my_files;
+       global $used_glossary_terms, $course_id, $course_language_charset, $course_language_code;
+       static $paths, $zipped_files;
+       global $glossary;
+       global $test_zipped_files, $use_a4a, $db;
+
+       $space  = '    ';
+       $prefix = '                    ';
+
+       if ($depth == 0) {
+               $string .= '<ul>';
+       }
+       $top_level = $_menu[$parent_id];
+       if (!is_array($paths)) {
+               $paths = array();
+       }
+       if (!is_array($zipped_files)) {
+               $zipped_files = array();
+       }
+       if ( is_array($top_level) ) {
+               
+               $counter = 1;
+               $num_items = count($top_level);
+               
+               foreach ($top_level as $garbage => $content) {
+                       $link = '';
+                               
+                       if ($content['content_path']) {
+                               $content['content_path'] .= '/';
+                       }
+                       //if this is a folder, export it without identifierref
+                       if ($content['content_type']==CONTENT_TYPE_FOLDER){
+                               $link = $prevfix.'<item identifier="MANIFEST01_ITEM'.$content['content_id'].'">'."\n";
+                       } else {
+                               $link = $prevfix.'<item identifier="MANIFEST01_ITEM'.$content['content_id'].'" identifierref="MANIFEST01_RESOURCE'.$content['content_id'].'" parameters="'.htmlentities($content['test_message'], ENT_QUOTES, 'UTF-8').'">'."\n";
+                       }
+                       $html_link = '<a href="resources/'.$content['content_path'].$content['content_id'].'.html" target="body">'.$content['title'].'</a>';    
+                       
+                       /* save the content as HTML files */
+                       /* @See: include/lib/format_content.inc.php */
+                       $content['text'] = str_replace('CONTENT_DIR/', '', $content['text']);
+                       /* get all the glossary terms used */
+                       $terms = find_terms($content['text']);
+                       if (is_array($terms)) {
+                               foreach ($terms[2] as $term) {
+                                       $used_glossary_terms[] = $term;
+                               }
+                       }
+
+                       /** Test dependency **/
+                       $test_dependency = '';  //Template for test
+                       $sql = 'SELECT * FROM '.TABLE_PREFIX.'content_tests_assoc WHERE content_id='.$content['content_id'];
+                       $result = mysql_query($sql, $db);
+                       while ($row = mysql_fetch_assoc($result)){
+                               //add test dependency ontop to forums dependency
+                               $test_dependency .= $prefix.$space.'<dependency identifierref="MANIFEST01_RESOURCE_QTI'.$row['test_id'].'" />';
+                       }
+
+                       /* calculate how deep this page is: */
+                       $path = '../';
+                       if ($content['content_path']) {
+                               $depth = substr_count($content['content_path'], '/');
+
+                               $path .= str_repeat('../', $depth);
+                       }
+                       
+                       $content['text'] = format_content($content['text'], $content['formatting'], $glossary, $path);
+
+                       /* add HTML header and footers to the files */
+                       
+                       /* use default style if <style> is not in imported html head */
+                       $head = '';
+                       if ($content['use_customized_head'])
+                       {
+                               if (strpos(strtolower($content['head']), '<style') > 0)
+                               {
+                                       $head = $content['head'];
+                               }
+                               else
+                               {
+                                       if (strlen($content['head']) > 0)  
+                                               $head = $content['head'] . $default_html_style;
+                                       else 
+                                               $head = $default_html_style;
+                               }
+                       }
+
+                       $content['text'] = str_replace( array('{TITLE}',        '{CONTENT}', '{KEYWORDS}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}', '{HEAD}'),
+                                                                       array($content['title'],        $content['text'], $content['keywords'], $course_language_charset, $course_language_code, $head),
+                                                                       $html_content_template);
+                                                               
+                       /* duplicate the paths in the content_path field in the zip file */
+                       if ($content['content_path']) {
+                               if (!in_array($content['content_path'], $paths)) {
+                                       $zipfile->create_dir('resources/'.$content['content_path'], time());
+                                       $paths[] = $content['content_path'];
+                               }
+                       }
+
+                       $zipfile->add_file($content['text'], 'resources/'.$content['content_path'].$content['content_id'].'.html', $content['u_ts']);
+                       $content['title'] = htmlspecialchars($content['title']);
+
+                       /* add the resource dependancies */
+                       if ($my_files == null) $my_files = array();
+                       $content_files = "\n";
+                       $parser->parse($content['text']);
+
+                       /* generate the IMS QTI resource and files */
+                       global $contentManager;
+                       //check if test export is allowed.
+                       if ($contentManager->allowTestExport($content['content_id'])){
+                               $content_test_rs = $contentManager->getContentTestsAssoc($content['content_id']);       
+                               $test_ids = array();            //reset test ids
+                               //$my_files = array();          //reset myfiles.
+                               while ($content_test_row = mysql_fetch_assoc($content_test_rs)){
+                                       //export
+                                       $test_ids[] = $content_test_row['test_id'];
+                                       //the 'added_files' is for adding into the manifest file in this zip
+                                       $added_files = test_qti_export($content_test_row['test_id'], '', $zipfile);
+
+                                       //Save all the xml files in this array, and then print_organizations will add it to the manifest file.
+                                       foreach($added_files as $filename=>$file_array){
+                                               $my_files[] = $filename;
+                                               foreach ($file_array as $garbage=>$filename2){
+                                                       if (!in_array($filename2, $my_files)){
+                                                               $my_files[] = $filename2;
+                                                       }
+                                               }
+                                       }
+
+                                       //Save all the xml files in this array, and then print_organizations will add it to the manifest file.
+                                       $resources .= str_replace(      array('{TEST_ID}', '{PATH}', '{FILES}'),
+                                                                                               array($content_test_row['test_id'], 'tests_'.$content_test_row['test_id'].'.xml', $added_files_xml),
+                                                                                               $ims_template_xml['resource_test']); 
+                               }
+                       }
+
+                       /* generate the a4a files */
+                       $a4a_xml_array = array();
+                       if ($use_a4a == true){
+                               $a4aExport = new A4aExport($content['content_id']);
+//                             $a4aExport->setRelativePath('resources/'.$content['content_path']);
+                               $secondary_files = $a4aExport->getAllSecondaryFiles();
+                               $a4a_xml_array = $a4aExport->exportA4a();
+                               $my_files = array_merge($my_files, $a4aExport->getAllSecondaryFiles());
+                       }
+
+                       /* handle @import */
+                       $import_files = get_import_files($content['text']);
+
+                       if (count($import_files) > 0) $my_files = array_merge($my_files, $import_files);
+
+                       foreach ($my_files as $file) {
+                               /* filter out full urls */
+                               $url_parts = @parse_url($file);
+                               if (isset($url_parts['scheme'])) {
+                                       continue;
+                               }
+
+                               /* file should be relative to content. let's double check */
+                               if ((substr($file, 0, 1) == '/')) {
+                                       continue;
+                               }
+
+                               $file_path = realpath(TR_CONTENT_DIR . $course_id . '/' . $content['content_path'] . $file);
+
+                               /* check if this file exists in the content dir, if not don't include it */
+                               if (file_exists($file_path) &&  is_file($file_path) && !in_array($file_path, $zipped_files)) {
+                                       $zipped_files[] = $file_path;
+                                       $dir = substr(dirname($file_path), strlen(TR_CONTENT_DIR . $course_id));
+
+                                       if (!in_array($dir, $paths) && $dir) {
+                                               $dir = str_replace('\\', '/', substr($dir, 1));
+                                               $zipfile->create_dir('resources/' . $dir, time());
+                                               
+                                               $paths[] = $dir;
+                                       }
+
+                                       $file_info = stat( $file_path );
+
+                                       //Fixes relative paths, so folder1/folder2/../file.jpg will become just folder1/file.jpg
+                                       $file_save_path = str_replace(TR_CONTENT_DIR . $course_id . DIRECTORY_SEPARATOR, '', $file_path);
+                                       $file_save_path = str_replace('\\', '/', $file_save_path);
+
+                                       //condition checks if the file has been added, so then the test won't be added to all the subchildren
+                                       //leads to normal images not capable to be extracted.
+                                       if ( (empty($test_zipped_files) || (is_array($test_zipped_files) && !in_array($file_path, $test_zipped_files))) 
+                                                && file_exists($file_path)){
+                                               $zipfile->add_file(@file_get_contents($file_path), 'resources/' . $file_save_path, $file_info['mtime']);
+//                                             $test_zipped_files[] = $content['content_path'] . $file;
+                                               $test_zipped_files[] = $file_path;
+                                       } elseif (!is_array($test_zipped_files) && file_exists($file_path) && !in_array($file_path, $zipped_files)){
+                                               $zipfile->add_file(@file_get_contents($file_path), 'resources/' . $file_save_path, $file_info['mtime']);
+                                       } 
+
+                                       //a4a secondary files have mapping, save the ones that we want in order to add the tag in
+                                       $a4a_secondary_files = array();
+                                       foreach ($a4a_xml_array as $a4a_filename=>$a4a_filearray){
+                                               if (preg_match('/(.*)\sto\s(.*)/', $a4a_filename, $matches)){
+                                                       //save the actual file name
+                                                       $a4a_secondary_files[$matches[1]][] = $a4a_filename;    //values are holders
+                                               }
+                                       }
+
+                                       // If this file has a4a alternatives, link it.
+                                       if (isset($a4a_xml_array[$file]) || isset($a4a_secondary_files[$file])){
+                                               //if this is an array, meaning that it has more than 1 alternatives, print all
+                                               if (is_array($a4a_secondary_files[$file])){
+                                                       $all_secondary_files_md = '';   //reinitialize string to null
+                                                       foreach ($a4a_secondary_files[$file] as $v){
+                                                               foreach($a4a_xml_array[$v] as $v2){
+                                                                       $all_secondary_files_md .= $v2; //all the meta data             
+                                                               }                                               
+                                                       }
+                                                       $content_files .= str_replace(  array('{FILE}', '{FILE_META_DATA}'), 
+                                                       array('resources/'.$file_save_path, $all_secondary_files_md), 
+                                                       $ims_template_xml['file_meta']);
+                                               } else {        
+                                                       $content_files .= str_replace(  array('{FILE}', '{FILE_META_DATA}'), 
+                                                       array('resources/'.$file_save_path, $a4a_xml_array[$file]), 
+                                                       $ims_template_xml['file_meta']);
+                                               }
+                                       } else {
+                                               //if this file is in the test array, add an extra link to the direct file, 
+                                               if (!empty($test_zipped_files) && in_array($file_path, $test_zipped_files)){
+                                                       $content_files .= str_replace('{FILE}', $file_save_path, $ims_template_xml['file']);
+                                               } else {
+                                                       $content_files .= str_replace('{FILE}', $file_save_path, $ims_template_xml['file']);
+                                               }
+                                       }
+                               }
+
+                               /* check if this file is one of the test xml file, if so, we need to add the dependency
+                                * Note:  The file has already been added to the archieve before this is called.
+                                */
+/* taken out as of nov 17th, used dependency instead
+                               if (preg_match('/tests\_[0-9]+\.xml$/', $file) && !in_array($file, $test_zipped_files)){
+                                       $content_files .= str_replace('{FILE}', $file, $ims_template_xml['xml']);
+                                       $test_zipped_files[] = $file;
+                               }
+*/
+                       }
+
+                       /******************************/
+                       $resources .= str_replace(      array('{CONTENT_ID}', '{PATH}', '{FILES}', '{DEPENDENCY}'),
+                                                                               array($content['content_id'], $content['content_path'], $content_files, $test_dependency),
+                                                                               $ims_template_xml['resource']);
+
+
+                       for ($i=0; $i<$depth; $i++) {
+                               $link .= $space;
+                       }
+                       
+                       $title = $prefix.$space.'<title>'.$content['title'].'</title>';
+
+                       if ( is_array($_menu[$content['content_id']]) ) {
+                               /* has children */
+
+                               $html_link = '<li>'.$html_link.'<ul>';
+                               for ($i=0; $i<$depth; $i++) {
+                                       if ($children[$i] == 1) {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       } else {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       }
+                               }
+
+                       } else {
+                               /* doesn't have children */
+
+                               $html_link = '<li>'.$html_link.'</li>';
+                               if ($counter == $num_items) {
+                                       for ($i=0; $i<$depth; $i++) {
+                                               if ($children[$i] == 1) {
+                                                       echo $space;
+                                                       //$html_link = $space.$html_link;
+                                               } else {
+                                                       echo $space;
+                                                       //$html_link = $space.$html_link;
+                                               }
+                                       }
+                               } else {
+                                       for ($i=0; $i<$depth; $i++) {
+                                               echo $space;
+                                               //$html_link = $space.$html_link;
+                                       }
+                               }
+                               $title = $space.$title;
+                       }
+
+                       echo $prefix.$link;
+                       echo $title;
+                       echo "\n";
+
+                       $string .= $html_link."\n";
+
+                       $depth ++;
+                       print_organizations($content['content_id'],
+                                                               $_menu, 
+                                                               $depth, 
+                                                               $path.$counter.'.', 
+                                                               $children,
+                                                               $string);
+                       $depth--;
+
+                       $counter++;
+                       for ($i=0; $i<$depth; $i++) {
+                               echo $space;
+                       }
+                       echo $prefix.'</item>';
+                       echo "\n";
+               }  
+
+               $string .= '</ul>';
+               if ($depth > 0) {
+                       $string .= '</li>';
+               }
+
+       }
+}
+
+$ims_template_xml['header'] = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
+<!--This is an ATutor SCORM 1.2 Content Package document-->
+<!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
+<manifest xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2" identifier="MANIFEST-'.md5(time()).'" 
+xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 http://www.imsglobal.org/xsd/imscp_v1p1p4.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 http://www.imsglobal.org/xsd/imsmd_v1p2p2.xsd http://www.imsglobal.org/xsd/imsqti_item_v2p0 http://www.imsglobal.org/xsd/imsqti_item_v2p0.xsd" 
+version = "CP 1.1.4">
+       <metadata>
+               <schema>ADL SCORM</schema> 
+           <schemaversion>1.2</schemaversion>
+               <imsmd:lom>
+                 <imsmd:general>
+                       <imsmd:title>
+                         <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_TITLE}</imsmd:langstring>
+                       </imsmd:title>
+                       <imsmd:description>
+                         <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_DESCRIPTION}</imsmd:langstring>
+                       </imsmd:description>
+                 </imsmd:general>
+                 <imsmd:lifecycle>
+                       <imsmd:contribute>
+                         <imsmd:role>
+                           <imsmd:source>
+                             <imsmd:langstring xml:lang="x-none">LOMv1.0</imsmd:langstring> 
+                           </imsmd:source>
+                           <imsmd:value>
+                             <imsmd:langstring xml:lang="x-none">Author</imsmd:langstring> 
+                           </imsmd:value>
+                         </imsmd:role>
+                         <imsmd:centity>
+                           <imsmd:vcard>{VCARD}</imsmd:vcard> 
+                         </imsmd:centity>
+                       </imsmd:contribute>
+                 </imsmd:lifecycle>
+                 <imsmd:educational>
+                       <imsmd:learningresourcetype>
+                         <imsmd:source>
+                               <imsmd:langstring xml:lang="x-none">ATutor</imsmd:langstring>
+                         </imsmd:source>
+                         <imsmd:value>
+                               <imsmd:langstring xml:lang="x-none">Content Module</imsmd:langstring>
+                         </imsmd:value>
+                       </imsmd:learningresourcetype>
+                 </imsmd:educational>
+                 <imsmd:rights>
+                 </imsmd:rights>
+               </imsmd:lom>
+       </metadata>
+';
+
+$ims_template_xml['resource'] = '              <resource identifier="MANIFEST01_RESOURCE{CONTENT_ID}" type="webcontent" href="resources/{PATH}{CONTENT_ID}.html"  adlcp:scormtype="asset">
+                       <metadata/>
+                       <file href="resources/{PATH}{CONTENT_ID}.html"/>{FILES}
+                       {DEPENDENCY}
+               </resource>
+'."\n";
+$ims_template_xml['resource_test'] = '         <resource identifier="MANIFEST01_RESOURCE_QTI{TEST_ID}" type="imsqti_xmlv1p2/imscc_xmlv1p0/assessment">
+                       <metadata/>
+                       <file href="{PATH}"/>{FILES}
+               </resource>
+'."\n";
+
+$ims_template_xml['file'] = '                  <file href="resources/{FILE}"/>'."\n";
+$ims_template_xml['xml'] = '                   <file href="{FILE}"/>'."\n";
+$ims_template_xml['file_meta'] = '                     <file href="{FILE}">
+                               <metadata>
+                               {FILE_META_DATA}
+                               </metadata>
+                       </file>'."\n";
+$ims_template_xml['final'] = '
+       <organizations default="MANIFEST01_ORG1">
+               <organization identifier="MANIFEST01_ORG1" structure="hierarchical">
+                       <title>{COURSE_TITLE}</title>
+{ORGANIZATIONS}
+               </organization>
+       </organizations>
+       <resources>
+{RESOURCES}
+       </resources>
+</manifest>';
+
+$html_template = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <style type="text/css">
+       body { font-family: Verdana, Arial, Helvetica, sans-serif;}
+       a.at-term {     font-style: italic; }
+       </style>
+       <title>{TITLE}</title>
+       <meta name="Generator" content="ATutor">
+       <meta name="Keywords" content="{KEYWORDS}">
+</head>
+<body>{CONTENT}</body>
+</html>';
+
+$html_content_template = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       {HEAD}
+       <title>{TITLE}</title>
+       <meta name="Generator" content="ATutor">
+       <meta name="Keywords" content="{KEYWORDS}">
+</head>
+<body>{CONTENT}</body>
+</html>';
+
+$default_html_style = '        <style type="text/css">
+       body { font-family: Verdana, Arial, Helvetica, sans-serif;}
+       a.at-term {     font-style: italic; }
+       </style>';
+       
+//output this as header.html
+$html_mainheader = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <link rel="stylesheet" type="text/css" href="ims.css"/>
+       <title>{COURSE_TITLE}</title>
+</head>
+<body class="headerbody"><h3>{COURSE_TITLE}</h3></body></html>';
+
+
+$html_toc = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <link rel="stylesheet" type="text/css" href="ims.css" />
+       <title></title>
+</head>
+<body>{TOC}</body></html>';
+
+// index.html
+$html_frame = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+   "http://www.w3.org/TR/html4/frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
+       <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
+       <title>{COURSE_TITLE}</title>
+</head>
+<frameset rows="50,*,50">
+<frame src="header.html" name="header" title="header" scrolling="no">
+       <frameset cols="25%, *" frameborder="1" framespacing="3">
+               <frame frameborder="2" marginwidth="0" marginheight="0" src="toc.html" name="frame" title="TOC">
+               <frame frameborder="2" src="resources/{PATH}{FIRST_ID}.html" name="body" title="{COURSE_TITLE}">
+       </frameset>
+<frame src="footer.html" name="footer" title="footer" scrolling="no">
+       <noframes>
+               <h1>{COURSE_TITLE}</h1>
+      <p><a href="toc.html">Table of Contents</a> | <a href="footer.html">About</a><br />
+         </p>
+  </noframes>
+</frameset>
+</html>';
+
+
+
+$glossary_xml = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
+<!--This is an ATutor Glossary terms document-->
+<!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
+
+<!DOCTYPE glossary [
+   <!ELEMENT item (term, definition)>
+   <!ELEMENT term (#PCDATA)>
+   <!ELEMENT definition (#PCDATA)>
+]>
+
+<glossary>
+      {GLOSSARY_TERMS}
+</glossary>
+';
+
+$glossary_term_xml = ' <item>
+               <term>{TERM}</term>
+               <definition>{DEFINITION}</definition>
+       </item>';
+
+$glossary_body_html = '<h2>Glossary</h2>
+       <ul>
+{BODY}
+</ul>';
+
+$glossary_term_html = '        <li><a name="{ENCODED_TERM}"></a><strong>{TERM}</strong><br />
+               {DEFINITION}<br /><br /></li>';
+
+?>
\ No newline at end of file
diff --git a/docs/home/ims/include/ims_xml.xsd b/docs/home/ims/include/ims_xml.xsd
new file mode 100644 (file)
index 0000000..dbb4ddc
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- filename=ims_xml.xsd -->
+<xsd:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
+       <!-- 2001-02-22 edited by Thomas Wason IMS Global Learning Consortium, Inc. -->
+       <xsd:annotation>
+               <xsd:documentation>In namespace-aware XML processors, the &quot;xml&quot; prefix is bound to the namespace name http://www.w3.org/XML/1998/namespace.</xsd:documentation>
+               <xsd:documentation>Do not reference this file in XML instances</xsd:documentation>
+       </xsd:annotation>
+       <xsd:attribute name="lang" type="xsd:language">
+               <xsd:annotation>
+                       <xsd:documentation>Refers to universal  XML 1.0 lang attribute</xsd:documentation>
+               </xsd:annotation>
+       </xsd:attribute>
+       <xsd:attribute name="base" type="xsd:anyURI">
+               <xsd:annotation>
+                       <xsd:documentation>Refers to XML Base: http://www.w3.org/TR/xmlbase</xsd:documentation>
+               </xsd:annotation>
+       </xsd:attribute>
+       <xsd:attribute name="link" type="xsd:anyURI"/>
+</xsd:schema>
diff --git a/docs/home/ims/include/imscp_rootv1p1p2.xsd b/docs/home/ims/include/imscp_rootv1p1p2.xsd
new file mode 100644 (file)
index 0000000..911a7f8
--- /dev/null
@@ -0,0 +1,345 @@
+<?xml version="1.0"?>
+
+<!-- edited with XML Spy v3.5 (http://www.xmlspy.com) by Thomas Wason (private) -->
+<!-- filename=ims_cp_rootv1p1p2.xsd -->
+<!-- Copyright (2) 2001 IMS Global Learning Consortium, Inc. -->
+<!-- edited by Thomas Wason  -->
+<!-- Conforms to w3c http://www.w3.org/TR/xmlschema-1/ 2000-10-24-->
+
+<xsd:schema xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2" 
+            targetNamespace="http://www.imsproject.org/xsd/imscp_rootv1p1p2" 
+            xmlns:xml="http://www.w3.org/XML/1998/namespace" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+            elementFormDefault="unqualified" version="IMS CP 1.1.2">
+
+   <!-- ******************** -->
+   <!-- ** Change History ** -->
+   <!-- ******************** -->
+   <xsd:annotation>
+      <xsd:documentation xml:lang="en">DRAFT XSD for IMS Content Packaging version 1.1 DRAFT</xsd:documentation>
+      <xsd:documentation> Copyright (c) 2001 IMS GLC, Inc. </xsd:documentation>
+      <xsd:documentation>2000-04-21, Adjustments by T.D. Wason from CP 1.0.</xsd:documentation>
+      <xsd:documentation>2001-02-22, T.D.Wason: Modify for 2000-10-24 XML-Schema version.  Modified to support extension.</xsd:documentation>
+      <xsd:documentation>2001-03-12, T.D.Wason: Change filename, target and meta-data namespaces and meta-data fielname.  Add meta-data to itemType, fileType and organizationType.</xsd:documentation>
+      <xsd:documentation>Do not define namespaces for xml in XML instances generated from this xsd.</xsd:documentation>
+      <xsd:documentation>Imports IMS meta-data xsd, lower case element names.         </xsd:documentation>
+      <xsd:documentation>This XSD provides a reference to the IMS meta-data root element as imsmd:record</xsd:documentation>
+      <xsd:documentation>If the IMS meta-data is to be used in the XML instance then the instance must define an IMS meta-data prefix with a namespace.  The meta-data targetNamespace should be used.  </xsd:documentation>
+      <xsd:documentation>2001-03-20, Thor Anderson: Remove manifestref, change resourceref back to identifierref, change manifest back to contained by manifest. --Tom Wason: manifest may contain _none_ or more manifests.</xsd:documentation>
+      <xsd:documentation>2001-04-13 Tom Wason: corrected attirbute name structure.  Was misnamed type.  </xsd:documentation>
+      <xsd:documentation>2001-05-14 Schawn Thropp: Made all complexType extensible with the group.any</xsd:documentation>
+      <xsd:documentation>Added the anyAttribute to all complexTypes. Changed the href attribute on the fileType and resourceType to xsd:string</xsd:documentation>
+      <xsd:documentation>Changed the maxLength of the href, identifierref, parameters, structure attributes to match the Information model.</xsd:documentation>
+      <xsd:documentation>2001-07-25 Schawn Thropp: Changed the namespace for the Schema of Schemas to the 5/2/2001 W3C XML Schema</xsd:documentation> 
+      <xsd:documentation>Recommendation. attributeGroup attr.imsmd deleted, was not used anywhere.  Any attribute declarations that have</xsd:documentation>
+      <xsd:documentation>use = "default" changed to use="optional" - attr.structure.req.</xsd:documentation>
+      <xsd:documentation>Any attribute declarations that have value="somevalue" changed to default="somevalue",</xsd:documentation>
+      <xsd:documentation>attr.structure.req (hierarchical).  Removed references to IMS MD Version 1.1.</xsd:documentation>
+      <xsd:documentation>Modified attribute group "attr.resourcetype.req" to change use from optional</xsd:documentation>
+      <xsd:documentation>to required to match the information model.  As a result the default value also needed to be removed</xsd:documentation> 
+      <xsd:documentation>Name change for XSD.  Changed to match version of CP Spec                                           </xsd:documentation> 
+   </xsd:annotation>
+
+   <xsd:annotation>
+      <xsd:documentation>Inclusions and Imports</xsd:documentation>
+   </xsd:annotation>
+
+   <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="ims_xml.xsd"/>
+
+   <xsd:annotation>
+      <xsd:documentation>Attribute Declarations</xsd:documentation>
+   </xsd:annotation>
+
+   <!-- **************************** -->
+   <!-- ** Attribute Declarations ** -->
+   <!-- **************************** -->
+   <xsd:attributeGroup name="attr.base">
+      <xsd:attribute ref="xml:base" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.default">
+      <xsd:attribute name="default" type="xsd:IDREF" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.href">
+      <xsd:attribute name="href" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:anyURI">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.href.req">
+      <xsd:attribute name="href" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:anyURI">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup> 
+
+   <xsd:attributeGroup name="attr.identifier.req">
+      <xsd:attribute name="identifier" type="xsd:ID" use="required"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.identifier">
+      <xsd:attribute name="identifier" type="xsd:ID" use="optional"/>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.isvisible">
+      <xsd:attribute name="isvisible" type="xsd:boolean" use="optional"/>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.parameters">
+      <xsd:attribute name="parameters" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="1000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.identifierref">
+      <xsd:attribute name="identifierref" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+   
+   <xsd:attributeGroup name="attr.identifierref.req">
+      <xsd:attribute name="identifierref" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="2000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+                
+   <xsd:attributeGroup name="attr.resourcetype.req">
+      <xsd:attribute name="type" use="required">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="1000"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.structure.req">
+      <xsd:attribute name="structure" use="optional" default="hierarchical">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="200"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:attributeGroup name="attr.version">
+      <xsd:attribute name="version" use="optional">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:maxLength value="20"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:annotation>
+       <xsd:documentation>element groups</xsd:documentation>
+   </xsd:annotation>
+
+   <xsd:group name="grp.any">
+      <xsd:annotation>
+         <xsd:documentation>Any namespaced element from any namespace may be included within an &quot;any&quot; element.  The namespace for the imported element must be defined in the instance, and the schema must be imported.  </xsd:documentation>
+      </xsd:annotation>
+      <xsd:sequence>
+         <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:group>
+
+   <!-- ************************** -->
+   <!-- ** Element Declarations ** -->
+   <!-- ************************** -->
+
+   <xsd:element name="dependency" type="dependencyType"/>
+   <xsd:element name="file" type="fileType"/>
+   <xsd:element name="item" type="itemType"/>
+   <xsd:element name="manifest" type="manifestType"/>
+   <xsd:element name="metadata" type="metadataType"/>
+   <xsd:element name="organization" type="organizationType"/>
+   <xsd:element name="organizations" type="organizationsType"/>
+   <xsd:element name="resource" type="resourceType"/>
+   <xsd:element name="resources" type="resourcesType"/>
+   <xsd:element name="schema" type="schemaType"/>
+   <xsd:element name="schemaversion" type="schemaversionType"/>
+   <xsd:element name="title" type="titleType"/>
+
+   <!-- ******************* -->
+   <!-- ** Complex Types ** -->
+   <!-- ******************* -->
+
+   <!-- **************** -->
+   <!-- ** dependency ** -->
+   <!-- **************** -->
+   <xsd:complexType name="dependencyType">
+      <xsd:sequence>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifierref.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ********** -->
+   <!-- ** file ** -->
+   <!-- ********** -->
+   <xsd:complexType name="fileType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.href.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ********** -->
+   <!-- ** item ** -->
+   <!-- ********** -->
+   <xsd:complexType name="itemType">
+      <xsd:sequence>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.identifierref"/>
+      <xsd:attributeGroup ref="attr.isvisible"/>
+      <xsd:attributeGroup ref="attr.parameters"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** manifest ** -->
+   <!-- ************** -->
+   <xsd:complexType name="manifestType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:element ref="organizations"/>
+         <xsd:element ref="resources"/>
+         <xsd:element ref="manifest" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.version"/>
+      <xsd:attribute ref="xml:base"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** metadata ** -->
+   <!-- ************** -->
+   <xsd:complexType name="metadataType">
+      <xsd:sequence>
+         <xsd:element ref="schema" minOccurs="0"/>
+         <xsd:element ref="schemaversion" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <!-- ******************* -->
+   <!-- ** organizations ** -->
+   <!-- ******************* -->
+   <xsd:complexType name="organizationsType">
+      <xsd:sequence>
+         <xsd:element ref="organization" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.default"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ****************** -->
+   <!-- ** organization ** -->
+   <!-- ****************** -->
+   <xsd:complexType name="organizationType">
+      <xsd:sequence>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.structure.req"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- *************** -->
+   <!-- ** resources ** -->
+   <!-- *************** -->
+   <xsd:complexType name="resourcesType">
+      <xsd:sequence>
+          <xsd:element ref="resource" minOccurs="0" maxOccurs="unbounded"/>
+          <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.base"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+   
+   <!-- ************** -->
+   <!-- ** resource ** -->
+   <!-- ************** -->
+   <xsd:complexType name="resourceType">
+      <xsd:sequence>
+         <xsd:element ref="metadata" minOccurs="0"/>
+         <xsd:element ref="file" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="dependency" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+      <xsd:attributeGroup ref="attr.identifier.req"/>
+      <xsd:attributeGroup ref="attr.resourcetype.req"/>
+      <xsd:attributeGroup ref="attr.base"/>
+      <xsd:attributeGroup ref="attr.href"/>
+      <xsd:anyAttribute namespace="##other" processContents="strict"/>
+   </xsd:complexType>
+
+   <!-- ****************** -->
+   <!-- ** Simple Types ** -->
+   <!-- ****************** -->
+
+   <!-- ************ -->
+   <!-- ** schema ** -->
+   <!-- ************ -->
+   <xsd:simpleType name="schemaType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="100"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+   
+   <!-- ******************* -->
+   <!-- ** schemaversion ** -->
+   <!-- ******************* -->
+   <xsd:simpleType name="schemaversionType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="20"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+   
+   <!-- *********** -->
+   <!-- ** title ** -->
+   <!-- *********** -->
+   <xsd:simpleType name="titleType">
+      <xsd:restriction base="xsd:string">
+         <xsd:maxLength value="200"/>
+      </xsd:restriction>
+   </xsd:simpleType>
+
+</xsd:schema>
diff --git a/docs/home/ims/include/imsmd_rootv1p2p1.xsd b/docs/home/ims/include/imsmd_rootv1p2p1.xsd
new file mode 100644 (file)
index 0000000..99bb356
--- /dev/null
@@ -0,0 +1,573 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited by Thomas Wason  -->
+<xsd:schema targetNamespace="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" 
+            xmlns:xml="http://www.w3.org/XML/1998/namespace" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+            xmlns="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1" 
+            elementFormDefault="qualified" 
+            version="1.2:1.1 IMS:MD1.2">
+
+   <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="ims_xml.xsd"/> 
+
+   <!-- ******************** -->
+   <!-- ** Change History ** -->
+   <!-- ******************** -->
+   <xsd:annotation>
+      <xsd:documentation>2001-04-26 T.D.Wason. IMS meta-data 1.2 XML-Schema.                                  </xsd:documentation>
+      <xsd:documentation>2001-06-07 S.E.Thropp. Changed the multiplicity on all elements to match the         </xsd:documentation>
+      <xsd:documentation>Final 1.2 Binding Specification.                                                     </xsd:documentation>
+      <xsd:documentation>Changed all elements that use the langstringType to a multiplicy of 1 or more        </xsd:documentation>
+      <xsd:documentation>Changed centity in the contribute element to have a multiplicity of 0 or more.       </xsd:documentation>
+      <xsd:documentation>Changed the requirement element to have a multiplicity of 0 or more.                 </xsd:documentation>
+      <xsd:documentation> 2001-07-25 Schawn Thropp.  Updates to bring the XSD up to speed with the W3C        </xsd:documentation>
+      <xsd:documentation> XML Schema Recommendation.  The following changes were made: Change the             </xsd:documentation>
+      <xsd:documentation> namespace to reference the 5/2/2001 W3C XML Schema Recommendation,the base          </xsd:documentation>
+      <xsd:documentation> type for the durtimeType, simpleType, was changed from timeDuration to duration.    </xsd:documentation>              
+      <xsd:documentation> Any attribute declarations that have use="default" had to change to use="optional"  </xsd:documentation>
+      <xsd:documentation> - attr.type.  Any attribute declarations that have value ="somevalue" had to change </xsd:documentation>
+      <xsd:documentation> to default = "somevalue" - attr.type (URI)                                          </xsd:documentation>
+      <xsd:documentation> 2001-09-04 Schawn Thropp                                                            </xsd:documentation>
+      <xsd:documentation> Changed the targetNamespace and namespace of schema to reflect version change       </xsd:documentation>
+   </xsd:annotation>
+
+   <!-- *************************** -->
+   <!-- ** Attribute Declaration ** -->
+   <!-- *************************** -->
+
+   <xsd:attributeGroup name="attr.type">
+      <xsd:attribute name="type" use="optional" default="URI">
+         <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+               <xsd:enumeration value="URI"/>
+               <xsd:enumeration value="TEXT"/>
+            </xsd:restriction>
+         </xsd:simpleType>
+      </xsd:attribute>
+   </xsd:attributeGroup>
+
+   <xsd:group name="grp.any">
+      <xsd:annotation>
+         <xsd:documentation>Any namespaced element from any namespace may be used for an &quot;any&quot; element.  The namespace for the imported element must be defined in the instance, and the schema must be imported.  </xsd:documentation>
+      </xsd:annotation>
+      <xsd:sequence>
+         <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:group>
+
+   <!-- ************************* -->
+   <!-- ** Element Declaration ** -->
+   <!-- ************************* -->
+
+   <xsd:element name="aggregationlevel" type="aggregationlevelType"/>
+   <xsd:element name="annotation" type="annotationType"/>
+   <xsd:element name="catalogentry" type="catalogentryType"/>
+   <xsd:element name="catalog" type="catalogType"/>
+   <xsd:element name="centity" type="centityType"/>
+   <xsd:element name="classification" type="classificationType"/>
+   <xsd:element name="context" type="contextType"/>
+   <xsd:element name="contribute" type="contributeType"/>
+   <xsd:element name="copyrightandotherrestrictions" type="copyrightandotherrestrictionsType"/>
+   <xsd:element name="cost" type="costType"/>
+   <xsd:element name="coverage" type="coverageType"/>
+   <xsd:element name="date" type="dateType"/>
+   <xsd:element name="datetime" type="datetimeType"/>
+   <xsd:element name="description" type="descriptionType"/>
+   <xsd:element name="difficulty" type="difficultyType"/>
+   <xsd:element name="educational" type="educationalType"/>
+   <xsd:element name="entry" type="entryType"/>
+   <xsd:element name="format" type="formatType"/>
+   <xsd:element name="general" type="generalType"/>
+   <xsd:element name="identifier" type="xsd:string"/>
+   <xsd:element name="intendedenduserrole" type="intendedenduserroleType"/>
+   <xsd:element name="interactivitylevel" type="interactivitylevelType"/>
+   <xsd:element name="interactivitytype" type="interactivitytypeType"/>
+   <xsd:element name="keyword" type="keywordType"/>
+   <xsd:element name="kind" type="kindType"/>
+   <xsd:element name="langstring" type="langstringType"/>
+   <xsd:element name="language" type="xsd:string"/>
+   <xsd:element name="learningresourcetype" type="learningresourcetypeType"/>
+   <xsd:element name="lifecycle" type="lifecycleType"/>
+   <xsd:element name="location" type="locationType"/>
+   <xsd:element name="lom" type="lomType"/>
+   <xsd:element name="maximumversion" type="minimumversionType"/>
+   <xsd:element name="metadatascheme" type="metadataschemeType"/>
+   <xsd:element name="metametadata" type="metametadataType"/>
+   <xsd:element name="minimumversion" type="maximumversionType"/>
+   <xsd:element name="name" type="nameType"/>
+   <xsd:element name="purpose" type="purposeType"/>
+   <xsd:element name="relation" type="relationType"/>
+   <xsd:element name="requirement" type="requirementType"/>
+   <xsd:element name="resource" type="resourceType"/>
+   <xsd:element name="rights" type="rightsType"/>
+   <xsd:element name="role" type="roleType"/>
+   <xsd:element name="semanticdensity" type="semanticdensityType"/>
+   <xsd:element name="size" type="sizeType"/>
+   <xsd:element name="source" type="sourceType"/>
+   <xsd:element name="status" type="statusType"/>
+   <xsd:element name="structure" type="structureType"/>
+   <xsd:element name="taxon" type="taxonType"/>
+   <xsd:element name="taxonpath" type="taxonpathType"/>
+   <xsd:element name="technical" type="technicalType"/>
+   <xsd:element name="title" type="titleType"/>
+   <xsd:element name="type" type="typeType"/>
+   <xsd:element name="typicalagerange" type="typicalagerangeType"/>
+   <xsd:element name="typicallearningtime" type="typicallearningtimeType"/>
+   <xsd:element name="value" type="valueType"/>
+   <xsd:element name="person" type="personType"/>
+   <xsd:element name="vcard" type="xsd:string"/>
+   <xsd:element name="version" type="versionType"/>
+   <xsd:element name="installationremarks" type="installationremarksType"/>
+   <xsd:element name="otherplatformrequirements" type="otherplatformrequirementsType"/>
+   <xsd:element name="duration" type="durationType"/>
+   <xsd:element name="id" type="idType"/>
+
+   <!-- ******************* -->
+   <!-- ** Complex Types ** -->
+   <!-- ******************* -->
+
+   <xsd:complexType name="aggregationlevelType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="annotationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="person" minOccurs="0"/>
+         <xsd:element ref="date" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="catalogentryType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="catalog"/>
+         <xsd:element ref="entry"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="centityType">
+      <xsd:sequence>
+         <xsd:element ref="vcard"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="classificationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="purpose" minOccurs="0"/>
+         <xsd:element ref="taxonpath" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="contextType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="contributeType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="role"/>
+         <xsd:element ref="centity" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="date" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="copyrightandotherrestrictionsType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="costType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="coverageType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="dateType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="descriptionType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="difficultyType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="durationType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="educationalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="interactivitytype" minOccurs="0"/>
+         <xsd:element ref="learningresourcetype" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="interactivitylevel" minOccurs="0"/>
+         <xsd:element ref="semanticdensity" minOccurs="0"/>
+         <xsd:element ref="intendedenduserrole" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="context" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="typicalagerange" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="difficulty" minOccurs="0"/>
+         <xsd:element ref="typicallearningtime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="language" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="entryType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="generalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="title" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="language" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="description" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="coverage" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="structure" minOccurs="0"/>
+         <xsd:element ref="aggregationlevel" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="installationremarksType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="intendedenduserroleType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="interactivitylevelType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="interactivitytypeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="keywordType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="kindType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="langstringType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attribute ref="xml:lang"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="learningresourcetypeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="lifecycleType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="version" minOccurs="0"/>
+         <xsd:element ref="status" minOccurs="0"/>
+         <xsd:element ref="contribute" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="locationType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attributeGroup ref="attr.type"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="lomType">
+      <xsd:sequence>
+         <xsd:element ref="general" minOccurs="0"/>
+         <xsd:element ref="lifecycle" minOccurs="0"/>
+         <xsd:element ref="metametadata" minOccurs="0"/>
+         <xsd:element ref="technical" minOccurs="0"/>
+         <xsd:element ref="educational" minOccurs="0"/>
+         <xsd:element ref="rights" minOccurs="0"/>
+         <xsd:element ref="relation" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="annotation" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="classification" minOccurs="0" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="metametadataType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="contribute" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="metadatascheme" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="language" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="nameType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="otherplatformrequirementsType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="personType">
+      <xsd:sequence>
+         <xsd:element ref="vcard"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="purposeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="relationType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="kind" minOccurs="0"/>
+         <xsd:element ref="resource" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="requirementType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="type" minOccurs="0"/>
+         <xsd:element ref="name" minOccurs="0"/>
+         <xsd:element ref="minimumversion" minOccurs="0"/>
+         <xsd:element ref="maximumversion" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="resourceType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="identifier" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:element ref="catalogentry" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="rightsType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="cost" minOccurs="0"/>
+         <xsd:element ref="copyrightandotherrestrictions" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="roleType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="semanticdensityType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="sourceType">
+      <xsd:sequence>
+         <xsd:element ref="langstring"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="statusType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="stringType">
+      <xsd:simpleContent>
+         <xsd:extension base="xsd:string">
+            <xsd:attribute ref="xml:lang"/>
+         </xsd:extension>
+      </xsd:simpleContent>
+   </xsd:complexType>
+   
+   <xsd:complexType name="structureType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="taxonpathType">
+      <xsd:sequence>
+         <xsd:element ref="source" minOccurs="0"/>
+         <xsd:element ref="taxon" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="taxonType">
+      <xsd:sequence>
+         <xsd:element ref="id" minOccurs="0"/>
+         <xsd:element ref="entry" minOccurs="0"/>
+         <xsd:element ref="taxon" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="technicalType" mixed="true">
+      <xsd:sequence>
+         <xsd:element ref="format" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="size" minOccurs="0"/>
+         <xsd:element ref="location" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="requirement" minOccurs="0" maxOccurs="unbounded"/>
+         <xsd:element ref="installationremarks" minOccurs="0"/>
+         <xsd:element ref="otherplatformrequirements" minOccurs="0"/>
+         <xsd:element ref="duration" minOccurs="0"/>
+         <xsd:group ref="grp.any"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="titleType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typeType">
+      <xsd:sequence>
+         <xsd:element ref="source"/>
+         <xsd:element ref="value"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typicalagerangeType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="typicallearningtimeType">
+      <xsd:sequence>
+         <xsd:element ref="datetime" minOccurs="0"/>
+         <xsd:element ref="description" minOccurs="0"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="valueType">
+      <xsd:sequence>
+         <xsd:element ref="langstring"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <xsd:complexType name="versionType">
+      <xsd:sequence>
+         <xsd:element ref="langstring" minOccurs="1" maxOccurs="unbounded"/>
+      </xsd:sequence>
+   </xsd:complexType>
+   
+   <!-- ****************** -->
+   <!-- ** Simple Types ** -->
+   <!-- ****************** -->
+   
+   <xsd:simpleType name="formatType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="sizeType">
+      <xsd:restriction base="xsd:int"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="datetimeType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="idType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="metadataschemeType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="catalogType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="minimumversionType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+   
+   <xsd:simpleType name="maximumversionType">
+      <xsd:restriction base="xsd:string"/>
+   </xsd:simpleType>
+
+</xsd:schema>
index 10c4b25..bb5491a 100644 (file)
@@ -19,18 +19,17 @@ require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php');
 require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php');
 require_once(TR_INCLUDE_PATH.'classes/DAO/UsersDAO.class.php');
 
-if (!isset($_REQUEST['course_id']) && !isset($_course_id) && $_course_id = 0)
+$course_id = (isset($_REQUEST['course_id']) ? intval($_REQUEST['course_id']) : $_course_id);
+$cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : $_content_id; /* content id of an optional chapter */
+$c   = isset($_REQUEST['c'])   ? intval($_REQUEST['c'])   : 0;
+
+if ($course_id == 0 && $cid == 0)
 {
        $msg->addError('MISSING_COURSE_ID');
        header('Location: ../index.php');
        exit;   
 }
 
-/* content id of an optional chapter */
-$course_id = (isset($_REQUEST['course_id']) ? $_REQUEST['course_id'] : $_course_id);
-$cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : $_content_id;
-$c   = isset($_REQUEST['c'])   ? intval($_REQUEST['c'])   : 0;
-
 if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
        /* for TILE */
 
@@ -237,7 +236,7 @@ $first = $content[$top_content_parent_id][0];
 $test_ids = array();   //global array to store all the test ids
 
 // Modified by Cindy Qi Li on Jan 12, 2010
-// Transformable does not have glossary and forums (discussion tools)
+// Transformable does not support glossary
 //TODO**************BOLOGNA***************REMOVE ME***************************/
 /*
 //Exoprt Forum:
@@ -286,7 +285,7 @@ ob_start();
 print_organizations($top_content_parent_id, $content, 0, '', array(), $toc_html);
 
 //Exoprt Forum:
-//print_resources_forum();
+print_resources_forum();
 
 $organizations_str = ob_get_contents();
 ob_end_clean();
diff --git a/docs/images/after.gif b/docs/images/after.gif
new file mode 100644 (file)
index 0000000..c05f3ed
Binary files /dev/null and b/docs/images/after.gif differ
diff --git a/docs/images/before.gif b/docs/images/before.gif
new file mode 100644 (file)
index 0000000..a1ba559
Binary files /dev/null and b/docs/images/before.gif differ
diff --git a/docs/images/child_of.gif b/docs/images/child_of.gif
new file mode 100644 (file)
index 0000000..3b48afb
Binary files /dev/null and b/docs/images/child_of.gif differ
index c7ef8ea..e9c00a2 100644 (file)
@@ -75,7 +75,10 @@ class ContentForumsAssocDAO extends DAO {
        */
        function getByContent($content_id)
        {
-           $sql = "SELECT * FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id = '".$content_id."'";
+           $sql = "SELECT f.forum_id, f.title, f.description
+                     FROM ".TABLE_PREFIX."content_forums_assoc cfa, ".TABLE_PREFIX."forums f 
+                    WHERE cfa.content_id = '".$content_id."'
+                      AND cfa.forum_id = f.forum_id";
            return $this->execute($sql);
        }
 }
index d66eec9..df76ff2 100644 (file)
@@ -141,7 +141,9 @@ class CoursesDAO extends DAO {
        {
                require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php');
                require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php');
+               require_once(TR_INCLUDE_PATH.'classes/DAO/ForumsCoursesDAO.class.php');
                $contentDAO = new ContentDAO();
+               $forumsCoursesDAO = new ForumsCoursesDAO();
                
                unset($_SESSION['s_cid']);
                
@@ -167,6 +169,9 @@ class CoursesDAO extends DAO {
                $sql = "DELETE FROM ".TABLE_PREFIX."tests WHERE course_id = ".$courseID;
                $this->execute($sql);
                
+               // delete forums that are associated with this course
+               $forumsCoursesDAO->DeleteByCourseID($courseID);
+               
                // loop thru content to delete using ContentDAO->Delete(), which deletes a4a objects as well
                $content_rows = $contentDAO->getContentByCourseID($courseID);
                if (is_array($content_rows)) {
diff --git a/docs/include/classes/DAO/ForumsCoursesDAO.class.php b/docs/include/classes/DAO/ForumsCoursesDAO.class.php
new file mode 100644 (file)
index 0000000..e35f3e8
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+/**
+* DAO for "forums_courses" table
+* @access      public
+* @author      Cindy Qi Li
+* @package     DAO
+*/
+
+if (!defined('TR_INCLUDE_PATH')) exit;
+
+require_once(TR_INCLUDE_PATH. 'classes/DAO/DAO.class.php');
+
+class ForumsCoursesDAO extends DAO {
+
+       /**
+       * Insert a new row
+       * @access  public
+       * @param   forum_id, course_id
+       * @return  true / false
+       * @author  Cindy Qi Li
+       */
+       function Create($forum_id, $course_id)
+       {
+               $sql =  'INSERT INTO ' . TABLE_PREFIX . 'forums_courses' . 
+                               '(forum_id, course_id) ' .
+                               'VALUES (' . $forum_id . ", $course_id)";
+           return $this->execute($sql);
+       }
+       
+       /**
+       * Delete row by course ID
+       * @access  public
+       * @param   courseID
+       * @return  true or false
+       * @author  Cindy Qi Li
+       */
+       function DeleteByCourseID($courseID)
+       {
+           include_once(TR_INCLUDE_PATH.'classes/DAO/ForumsDAO.class.php');
+           $forumsDAO = new ForumsDAO();
+           
+               $all_forums = $this->getByCourse($courseID);
+           if (is_array($all_forums)) {
+               foreach ($all_forums as $forums) {
+                       $forumsDAO->Delete($forums['forum_id']);
+               }
+           }
+               $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses 
+                    WHERE course_id = ".$courseID."";
+           return $this->execute($sql);
+       }
+       
+       /**
+       * Delete row by forum ID
+       * @access  public
+       * @param   forumID
+       * @return  true or false
+       * @author  Cindy Qi Li
+       */
+       function DeleteByForumID($forumID)
+       {
+           $sql = "DELETE FROM ".TABLE_PREFIX."forums_courses 
+                    WHERE forum_id = ".$forumID."";
+           return $this->execute($sql);
+       }
+       
+       /**
+       * Return rows by course ID
+       * @access  public
+       * @param   name
+       * @return  table rows
+       * @author  Cindy Qi Li
+       */
+       function getByCourse($course_id)
+       {
+           $sql = "SELECT * FROM ".TABLE_PREFIX."forums_courses WHERE course_id = '".$course_id."'";
+           return $this->execute($sql);
+       }
+}
+?>
\ No newline at end of file
diff --git a/docs/include/classes/DAO/ForumsDAO.class.php b/docs/include/classes/DAO/ForumsDAO.class.php
new file mode 100644 (file)
index 0000000..e58d3da
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+/**
+ * DAO for "forums" table
+ * @access     public
+ * @author     Cindy Qi Li
+ * @package    DAO
+ */
+
+if (!defined('TR_INCLUDE_PATH')) exit;
+
+require_once(TR_INCLUDE_PATH. 'classes/DAO/DAO.class.php');
+
+class ForumsDAO extends DAO {
+
+       /**
+        * Create new forums
+        * @access  public
+        * @param   
+        * @return  user id, if successful
+        *          false and add error into global var $msg, if unsuccessful
+        * @author  Cindy Qi Li
+        */
+       public function Create($title, $description)
+       {
+               global $addslashes;
+
+               $title = $addslashes(trim($title));
+               $decsription = $addslashes(trim($description));
+               
+               if ($this->isFieldsValid($title))
+               {
+                       /* insert into the db */
+                       $sql = "INSERT INTO ".TABLE_PREFIX."forums
+                                     (title, description, created_date)
+                              VALUES ('".$title."',
+                                      '".$decsription."',
+                                      now())";
+
+                       if (!$this->execute($sql))
+                       {
+                               $msg->addError('DB_NOT_UPDATED');
+                               return false;
+                       }
+                       else
+                       {
+                               return mysql_insert_id();
+                       }
+               }
+               else
+               {
+                       return false;
+               }
+       }
+
+       /**
+        * Delete a forum
+        * @access  public
+        * @param   forum ID
+        * @return  true, if successful
+        *          false and add error into global var $msg, if unsuccessful
+        * @author  Cindy Qi Li
+        */
+       public function Delete($forumID)
+       {
+               require_once(TR_INCLUDE_PATH.'classes/FileUtility.class.php');
+               require_once(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php');
+               $contentForumsAssocDAO = new ContentForumsAssocDAO();
+               
+               // delete the forum and related data
+               $contentForumsAssocDAO->DeleteByForumID($forumID);
+               
+               $sql = "DELETE FROM ".TABLE_PREFIX."forums
+                        WHERE forum_id = ".$forumID;
+               $this->execute($sql);
+       }
+
+       /**
+        * Return by given forum id
+        * @access  public
+        * @param   forum id
+        * @return  one row
+        * @author  Cindy Qi Li
+        */
+       public function get($forumID)
+       {
+               $sql = 'SELECT * FROM '.TABLE_PREFIX.'forums WHERE forum_id='.$forumID;
+               if ($rows = $this->execute($sql))
+               {
+                       return $rows[0];
+               }
+               else return false;
+       }
+
+       /**
+        * Validate fields preparing for insert and update
+        * @access  private
+        * @param   $title
+        * @return  true    if update successfully
+        *          false   if update unsuccessful
+        * @author  Cindy Qi Li
+        */
+       private function isFieldsValid($title)
+       {
+               global $msg;
+               
+               $missing_fields = array();
+               
+               if ($title == '')
+               {
+                       $missing_fields[] = _AT('title');
+               }
+               
+               if ($missing_fields)
+               {
+                       $missing_fields = implode(', ', $missing_fields);
+                       $msg->addError(array('EMPTY_FIELDS', $missing_fields));
+               }
+               
+               if (!$msg->containsErrors())
+                       return true;
+               else
+                       return false;
+       }
+}
+?>
\ No newline at end of file
diff --git a/docs/include/classes/DiscussionTools/DiscussionTools.class.php b/docs/include/classes/DiscussionTools/DiscussionTools.class.php
new file mode 100644 (file)
index 0000000..65a34d5
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+/**
+ * A class for DiscussionTools
+ * based on:
+ *  http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_5/imsdt_v1p0_localised.xsd
+ */
+class DiscussionTools {
+       //global variables
+       var $title = '';        //The Forum title
+       var $text = '';         //The description of the discussion tools.
+
+       //constructor
+       function DiscussionTools($title, $text){
+               $this->title = $title;
+               $this->text = $text;
+       }
+
+       function getTitle(){
+               return htmlspecialchars(trim($this->title));
+       }
+
+       function getText(){
+               //change the $IMS-CC-FILEBASE$ to the base of this directory
+               //TODO: The returned value may contains HTML, ATutor doesn't check 
+               //              if it contains malicious javascript at this point.
+               $this->text = preg_replace('/\$IMS\-CC\-FILEBASE\$/', '', $this->text);
+               return trim(html_entity_decode($this->text));
+       }
+}
+?>
\ No newline at end of file
diff --git a/docs/include/classes/DiscussionTools/DiscussionToolsImport.class.php b/docs/include/classes/DiscussionTools/DiscussionToolsImport.class.php
new file mode 100644 (file)
index 0000000..58e33f3
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+include(TR_INCLUDE_PATH.'classes/DAO/ForumsDAO.class.php');
+include(TR_INCLUDE_PATH.'classes/DAO/ForumsCoursesDAO.class.php');
+include(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php');
+
+/**
+ * A class for DiscussionToolsParser
+ * based on:
+ *  http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_5/imsdt_v1p0_localised.xsd
+ */
+class DiscussionToolsImport {
+       //global variables
+       var $fid;       //the forum id that is imported 
+
+       //constructor
+       function DiscussionToolsImport(){}
+
+       //import
+       function import($forum_obj, $cid, $course_id){
+               $title = $forum_obj->getTitle();
+               $text = $forum_obj->getText();
+
+               $this->fid = $this->createForum($title, $text, $course_id);
+               $this->associateForum($cid, $this->fid);
+       }
+
+       
+       /**
+        * create a forum
+        * @param       string  title
+        * @param       string  text/description
+        * @return      added forum's id
+        */
+       function createForum($title, $text, $course_id){
+               $forumsDAO = new ForumsDAO();
+               $forums_id = $forumsDAO->Create($title, $text);
+               
+               $forumsCoursesDAO = new ForumsCoursesDAO();
+               $forumsCoursesDAO->Create($forums_id, $course_id);
+               
+               return $forums_id;
+       }       
+
+
+       /**
+        * create an association between forum and content
+        * @param       int             content id
+        * @return      
+        */
+       function associateForum($cid, $fid){
+               $contentForumsAssocDAO = new ContentForumsAssocDAO();
+               return $contentForumsAssocDAO->Create($cid, $fid);
+       }
+
+       /**
+        * Return the fid that was created by this import
+        * @return      int      forum id.
+        */
+       function getFid(){
+               return $this->fid;
+       }
+}
+?>
\ No newline at end of file
diff --git a/docs/include/classes/DiscussionTools/DiscussionToolsParser.class.php b/docs/include/classes/DiscussionTools/DiscussionToolsParser.class.php
new file mode 100644 (file)
index 0000000..2a840a3
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+include('DiscussionTools.class.php');
+
+/**
+ * A class for DiscussionToolsParser
+ * based on:
+ *  http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_5/imsdt_v1p0_localised.xsd
+ */
+class DiscussionToolsParser {
+       //global variables
+       //private
+       var $parser; // the XML handler
+       var $character_data; // tmp variable for storing the data
+       var $element_path; // array of element paths (basically a stack)
+       var $title;     //link's title
+       var $text; //description
+
+       //constructor
+       function DiscussionToolsParser(){
+               $this->parser = xml_parser_create(); 
+
+               xml_set_object($this->parser, $this);
+               xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
+               xml_set_element_handler($this->parser, 'startElement', 'endElement');
+               xml_set_character_data_handler($this->parser, 'characterData');
+       }
+
+       // public
+       // @return      true if parsed successfully, false otherwise
+       function parse($xml_data) {
+               $this->element_path   = array();
+               $this->character_data = '';
+               xml_parse($this->parser, $xml_data, TRUE);              
+       }
+
+       // private
+       function startElement($parser, $name, $attributes) {
+               //save attributes.
+               switch($name) {
+                       case 'text':
+                               $this->text_type = $attributes['texttype'];
+                               break;
+               }
+               array_push($this->element_path, $name);
+   }
+
+       // private
+       /* called when an element ends */
+       /* removed the current element from the $path */
+       function endElement($parser, $name) {
+               switch($name) {
+                       case 'title':
+                               $this->title = $this->character_data;
+                               break;
+                       case 'text':
+                               $this->text = $this->character_data;
+                               break;
+               }
+
+               //pop stack and reset character data, o/w it will stack up
+               array_pop($this->element_path);
+               $this->character_data = '';
+       }
+
+       // private      
+       function characterData($parser, $data){
+               global $addslashes;
+               if (trim($data)!=''){
+                       $this->character_data .= preg_replace('/[\t\0\x0B(\r\n)]*/', '', $data);
+//                     $this->character_data .= trim($data);
+               }
+       }
+
+       //public
+       function close(){
+               //Free the XML parser
+               xml_parser_free($this->parser);
+       }
+
+       //get title
+       function getDT(){
+               return new DiscussionTools($this->title, $this->text);
+       }
+}
+?>
\ No newline at end of file
index 890a69a..35ce270 100644 (file)
@@ -58,9 +58,10 @@ function print_organizations($parent_id,
        global $test_list, $test_zipped_files, $test_files, $test_xml_items, $use_a4a;
        global $contentManager;
         /* added by bologna*///TODO***********BOLOGNA**************REMOVE ME*****************/
-        global $db,$forum_list;//forum_list contiene tutti i forum distinti associati ai contenuti. poich� la funzione in questione � ricorsiva deve essere globale in modo che in fase di creazione dell'archivio zip i file descrittori dei forum non vengano ripetuti
+       global $db,$forum_list;//forum_list contiene tutti i forum distinti associati ai contenuti. poich� la funzione in questione � ricorsiva deve essere globale in modo che in fase di creazione dell'archivio zip i file descrittori dei forum non vengano ripetuti
 
        require_once(TR_INCLUDE_PATH.'../home/classes/ContentUtility.class.php');
+       require_once(TR_INCLUDE_PATH.'classes/DAO/ContentForumsAssocDAO.class.php');
        
        $space  = '    ';
        $prefix = '                    ';
@@ -119,7 +120,7 @@ function print_organizations($parent_id,
                        /* @See: include/lib/format_content.inc.php */
                        $content['text'] = str_replace('CONTENT_DIR/', '', $content['text']);
                        /* Commented by Cindy Qi Li on Jan 12, 2010
-                        * Transformable does not support glossary and forum (discussion tools)
+                        * Transformable does not support glossary
                        // get all the glossary terms used
                        $terms = find_terms($content['text']);
                        if (is_array($terms)) {
@@ -127,39 +128,33 @@ function print_organizations($parent_id,
                                        $used_glossary_terms[] = $term;
                                }
                        }
-
-
-                    // TODO-----------BOLOGNA------------REMOVE ME-------------/
-                    $f_count = count($forum_list); //count all distinct forum_id associated to a content page
+*/
+                       $f_count = count($forum_list); //count all distinct forum_id associated to a content page
                                                 //la funzione è ricorsiva quindi lo devo ricavare attraverso la variabile globale forum_list
 
-                    // TODO-----------BOLOGNA------------REMOVE ME-------------/
-                    //recupero i forum associati al contenuto corrente
-                    $sql = "SELECT cf.forum_id, f.title, f.description FROM (SELECT * FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content[content_id]) AS cf LEFT JOIN ".TABLE_PREFIX."forums f ON cf.forum_id=f.forum_id";
-                    $result_cf = mysql_query($sql,$db);
-                    $cf_count = mysql_num_rows($result_cf);
+                       $contentForumsAssocDAO = new ContentForumsAssocDAO();
+                       $forums = $contentForumsAssocDAO->getByContent($content[content_id]);
+//                    $sql = "SELECT cf.forum_id, f.title, f.description FROM (SELECT * FROM ".TABLE_PREFIX."content_forums_assoc WHERE content_id=$content[content_id]) AS cf LEFT JOIN ".TABLE_PREFIX."forums f ON cf.forum_id=f.forum_id";
+//                    $result_cf = mysql_query($sql,$db);
    
-                    //per ogni forum ottenuto controllo se è già stato caricato nell'array
-                    //necessario mantenerlo distinto poichè NON si prevedono funzioni sul
-                    //controllo dei nomi nell'inserimento di file nell'archivio.
-                    $find=false;
-                    $forums_dependency='';  //template for associate Discussion Topic to the current content into the manifest
-                    while($current_forum = mysql_fetch_assoc($result_cf)) {
-                        for($j=0;$j<$f_count;$j++) {
-                            if($forum_list[$j]['id'] == $current_forum['forum_id'])
-                                $find= true;
-                        }
-                        if(!$find) {
-
-                            $forum_list[$f_count]['id']=$current_forum['forum_id'];
-                            $forum_list[$f_count]['title']=$current_forum['title'];
-                            $forum_list[$f_count]['description']=$current_forum['description'];
-                            $find=false;
-                            $f_count++;
-                        }
-                       $forums_dependency .= $prefix.$space.'<dependency identifierref="Forum'.$current_forum['forum_id'].'_R" />';
-                    }
-*/
+                       $find=false;
+                       $forums_dependency='';  //template for associate Discussion Topic to the current content into the manifest
+                       if (is_array($forums)) {
+                               foreach($forums as $current_forum) {
+                                       for($j=0;$j<$f_count;$j++) {
+                                               if($forum_list[$j]['id'] == $current_forum['forum_id']) $find= true;
+                                       }
+                                       if(!$find) {
+                                               $forum_list[$f_count]['id']=$current_forum['forum_id'];
+                                               $forum_list[$f_count]['title']=$current_forum['title'];
+                                               $forum_list[$f_count]['description']=$current_forum['description'];
+                                               $find=false;
+                                               $f_count++;
+                                       }
+                               }
+                               $forums_dependency .= $prefix.$space.'<dependency identifierref="Forum'.$current_forum['forum_id'].'_R" />';
+            }
+
                         /** Test dependency **/
                        require_once(TR_INCLUDE_PATH.'classes/DAO/ContentTestsAssocDAO.class.php');
                        $contentTestsAssocDAO = new ContentTestsAssocDAO();
index cae1be0..fabb287 100644 (file)
@@ -154,6 +154,10 @@ if (array_key_exists(TR_PRIV_HOME, $privs) && Utility::authenticate($privs[TR_PR
                \r
                $_pages['home/editor/accessibility.php']['title_var'] = 'accessibility';\r
                $_pages['home/editor/accessibility.php']['parent']    = 'home/editor/edit_content.php';\r
+\r
+               $_pages['home/editor/import_export_content.php']['title_var']    = 'content_packaging';\r
+               $_pages['home/editor/import_export_content.php']['parent']   = 'home/index.php';\r
+               $_pages['home/editor/import_export_content.php']['guide']     = 'TR_HELP_IMPORT_EXPORT_CONTENT';\r
        }\r
 }\r
 \r
index b4a1bd3..2d93d99 100644 (file)
@@ -102,6 +102,16 @@ CREATE TABLE `forums` (
   PRIMARY KEY  (`forum_id`)\r
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;\r
 \r
+# --------------------------------------------------------\r
+# Table structure for table `forums_courses`\r
+# since 0.1\r
+\r
+CREATE TABLE `forums_courses` (\r
+  `forum_id` MEDIUMINT UNSIGNED NOT NULL default '0',\r
+  `course_id` MEDIUMINT UNSIGNED NOT NULL default '0',\r
+  PRIMARY KEY (`forum_id`,`course_id`)\r
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;\r
+\r
 # --------------------------------------------------------\r
 # Table structure for table `languages`\r
 # since 0.1\r
index 8f40ddc..11956cf 100644 (file)
@@ -438,7 +438,28 @@ INSERT INTO `TR_language_text` VALUES ('en', '_template', 'stop_apply_visual_alt
 INSERT INTO `TR_language_text` VALUES ('en', '_template', 'apply_visual_alternatives', 'Apply Visual Alternatives', now(), '');\r
 INSERT INTO `TR_language_text` VALUES ('en', '_template', 'stop_apply_sign_lang_alternatives', 'Stop Applying Sign Language Alternatives', now(), '');\r
 INSERT INTO `TR_language_text` VALUES ('en', '_template', 'apply_sign_lang_alternatives', 'Apply Sign Language Alternatives', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'editor_properties_instructions', 'Select the radio button of the content you want to move. Use the %1$s and %2$s buttons to place this topic after or before the selected location, respectively. Use the %3$s button to add this topic as a child of the selected location.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'after_topic', 'After: %s', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'before_topic', 'Before: %s', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'child_of', 'Child of: %s', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'forums', 'Forums', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'content_packaging', 'Import/Export Content', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'export_content_info', 'Export content as an <strong>IMS or SCORM conformant content package</strong>, or as an <strong>IMS Common Cartridge</strong>. Import the zipped package or cartridge into another ATutor system or another course, or into another conformant LMS or LCMS.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'export_content_package_what', 'What to export', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'export_entire_course_or_chap', 'Entire course, or select a chapter below', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'content_package', 'Content Package', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'common_cartridge', 'Common Cartridge', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'a4a_export', 'Export AccessForAll adapted content.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'none_found', 'None Found.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'import_content', 'Import Content', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'import_content_info', 'Import a conformant IMS content package or IMS common cartridge. Select a location within the existing content to <strong>import into</strong>.  Or enter a URL to content package or common cartridge, to import directly from the Web.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'import_content_package_where', 'Import into', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'import_content_package_bottom_subcontent', 'As top level content, or as subcontent selected below', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'test_import_package', 'Import available tests.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'a4a_import_package', 'Import available AccessForAll adapted content.', now(), '');\r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', 'upload_content_package', 'Upload a Content Package or Common Cartridge', now(), '');\r
 \r
+INSERT INTO `TR_language_text` VALUES ('en', '_template', '', '', now(), '');\r
 INSERT INTO `TR_language_text` VALUES ('en', '_template', '', '', now(), '');\r
 INSERT INTO `TR_language_text` VALUES ('en', '_template', '', '', now(), '');\r
 INSERT INTO `TR_language_text` VALUES ('en', '_template', '', '', now(), '');\r
index df6f9f8..da3d352 100644 (file)
@@ -88,6 +88,22 @@ if ($_SESSION["prefs"]["PREF_SHOW_CONTENTS"] && $this->content_table <> "")
 </div>\r
 <?php endif; ?>\r
 \r
+<?php if (is_array($this->forum_ids)): ?>\r
+<div id="content-test" class="input-form">\r
+    <ol>\r
+        <strong><?php echo _AT('forums') . ':' ; ?></strong>\r
+            <ul class="tools">\r
+                <?php\r
+                foreach ($this->forum_ids as $id => $forum_obj) {\r
+                    echo '<li>'.AT_print($forum_obj['title'], 'forums.title').'<br /></li>';\r
+                }\r
+                ?>\r
+            </ul>\r
+        </li>\r
+    </ol>\r
+</div>\r
+<?php endif; ?>\r
+\r
 <div id="content-info">\r
        <?php echo $this->content_info; ?>\r
 \r
diff --git a/docs/themes/default/home/editor/arrange_content.tmpl.php b/docs/themes/default/home/editor/arrange_content.tmpl.php
new file mode 100644 (file)
index 0000000..615380a
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/************************************************************************/
+/* Transformable                                                        */
+/************************************************************************/
+/* Copyright (c) 2009                                                   */
+/* Adaptive Technology Resource Centre / University of Toronto          */
+/*                                                                      */
+/* This program 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.                        */
+/************************************************************************/
+
+if (!defined('TR_INCLUDE_PATH')) { exit; } 
+
+global $contentManager;
+
+require(TR_INCLUDE_PATH.'header.inc.php');
+?>
+<div class="input-form">
+<form action="<?php echo $_SERVER['PHP_SELF'].'?_course_id='.$this->course_id; if ($this->cid > 0) echo SEP.'_cid='.$this->cid; else if ($this->pid > 0) echo SEP.'pid='.$this->pid;?>" method="post" name="form"> 
+       <input type="hidden" name="button_1" value="-1" />
+<?php
+       if ($contentManager->getNumSections() > (1 - (bool)(!$cid))) {
+               echo '<p>' 
+                       , _AT('editor_properties_instructions', 
+                               '<img src="'.$_base_path.'images/after.gif" alt="'._AT('after_topic', '').'" title="'._AT('after_topic', '').'" />', 
+                               '<img src="'.$_base_path.'images/before.gif" alt="'._AT('before_topic', '').'" title="'._AT('before_topic', '').'" />',
+                               '<img src="'.$_base_path.'images/child_of.gif" alt="'._AT('child_of', '').'" title="'._AT('child_of', '').'"  />')
+                       , '</p>';
+
+       }
+
+       ?><br />
+       <table border="0" align="center">
+       <tr>
+               <th colspan="3"><?php echo _AT('move'); ?></th>
+               <th><?php echo _AT('content'); ?></th>
+       </tr>
+       <tr>
+               <td colspan="3">&nbsp;</td>
+               <td><?php echo _AT('home'); ?></td>
+       </tr>
+<?php
+               $contentManager->printActionMenu($contentManager->_menu, 0, 0, '', array(), "movable");
+                       
+?>
+       </table>
+</form>
+</div>
+<?php require(TR_INCLUDE_PATH.'footer.inc.php'); ?>
\ No newline at end of file
index 37a0f8c..f99fe44 100644 (file)
Binary files a/docs/themes/default/images/Thumbs.db and b/docs/themes/default/images/Thumbs.db differ
diff --git a/docs/themes/default/images/arrange_content.gif b/docs/themes/default/images/arrange_content.gif
new file mode 100644 (file)
index 0000000..8205750
Binary files /dev/null and b/docs/themes/default/images/arrange_content.gif differ
index 45166c2..1380214 100644 (file)
@@ -206,6 +206,12 @@ foreach ($this->top_level_pages as $page) {
       <a href="<?php echo $this->base_path; ?>home/course/course_property.php?_course_id=<?php echo $this->course_id; ?>">
         <img src="<?php echo $this->base_path. "themes/".$this->theme."/images/course_property.png"; ?>" title="<?php echo _AT('course_property'); ?>" alt="<?php echo _AT('course_property'); ?>" border="0" />
       </a> &nbsp;
+      <a href="<?php echo $this->base_path; ?>home/editor/arrange_content.php?_course_id=<?php echo $this->course_id; ?>">
+        <img src="<?php echo $this->base_path. "themes/".$this->theme."/images/arrange_content.gif"; ?>" title="<?php echo _AT('arrange_content'); ?>" alt="<?php echo _AT('arrange_content'); ?>" border="0" />
+      </a> &nbsp;
+      <a href="<?php echo $this->base_path; ?>home/editor/import_export_content.php?_course_id=<?php echo $this->course_id; ?>">
+        <img src="<?php echo $this->base_path. "themes/".$this->theme."/images/import_export.png"; ?>" title="<?php echo _AT('content_packaging'); ?>" alt="<?php echo _AT('content_packaging'); ?>" border="0" />
+      </a> &nbsp;
       <a href="<?php echo $this->base_path; ?>home/course/del_course.php?_course_id=<?php echo $this->course_id; ?>">
         <img src="<?php echo $this->base_path. "themes/".$this->theme."/images/delete.gif"; ?>" title="<?php echo _AT('del_course'); ?>" alt="<?php echo _AT('del_course'); ?>" border="0" />
       </a> &nbsp;
@@ -214,7 +220,7 @@ foreach ($this->top_level_pages as $page) {
         <img src="<?php echo $this->base_path. "themes/".$this->theme."/images/exit.png"; ?>" title="<?php echo _AT('exit_course'); ?>" alt="<?php echo _AT('exit_course'); ?>" border="0" />
       </a>
     <?php }?>
   </div>
+ </div>
 <?php  
 //if ($this->course_id > 0) {
 ?>