2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2010 */
6 /* Inclusive Design Institute */
8 /* This program is free software. You can redistribute it and/or */
9 /* modify it under the terms of the GNU General Public License */
10 /* as published by the Free Software Foundation. */
11 /************************************************************************/
13 define('TR_INCLUDE_PATH', '../../include/');
14 require_once(TR_INCLUDE_PATH.'vitals.inc.php');
15 global $_course_id, $_content_id;
17 require_once(TR_INCLUDE_PATH.'../home/classes/ContentManager.class.php'); /* content management class */
18 require_once(TR_INCLUDE_PATH.'classes/DAO/CoursesDAO.class.php');
19 require_once(TR_INCLUDE_PATH.'classes/DAO/ContentDAO.class.php');
20 require_once(TR_INCLUDE_PATH.'classes/DAO/UsersDAO.class.php');
22 $_course_id = $course_id = (isset($_REQUEST['course_id']) ? intval($_REQUEST['course_id']) : $_course_id);
23 $_content_id = $cid = isset($_REQUEST['cid']) ? intval($_REQUEST['cid']) : $_content_id; /* content id of an optional chapter */
24 $c = isset($_REQUEST['c']) ? intval($_REQUEST['c']) : 0;
26 if ($course_id == 0 && $cid == 0)
28 $msg->addError('MISSING_COURSE_ID');
29 header('Location: ../index.php');
33 if (isset($_REQUEST['to_tile']) && !isset($_POST['cancel'])) {
34 /* export from AContent to atutor */
36 require_once(TR_INCLUDE_PATH.'vitals.inc.php');
37 if (!authenticate(TR_PRIV_ADMIN, TR_PRIV_RETURN)) {
38 /* user can't be authenticated */
39 header('HTTP/1.1 404 Not Found');
40 echo 'Document not found.';
44 $m = md5(DB_PASSWORD . 'x' . ADMIN_PASSWORD . 'x' . $_SERVER['SERVER_ADDR'] . 'x' . $cid . 'x' . $_SESSION['course_id'] . 'x' . date('Ymd'));
46 header('Location: '.TR_TILE_IMPORT. '?cp='.urlencode(TR_BASE_HREF. 'tools/imscc/ims_export.php?cid='.$cid.'&c='.$_SESSION['course_id'].'&m='.$m));
48 } else if (isset($_GET['m'])) {
51 /* request (hopefully) coming from a TILE server, send the content package */
53 $_user_location = 'public';
54 // require_once(TR_INCLUDE_PATH.'vitals.inc.php');
55 $m = md5(DB_PASSWORD . 'x' . ADMIN_PASSWORD . 'x' . $_SERVER['SERVER_ADDR'] . 'x' . $cid . 'x' . $c . 'x' . date('Ymd'));
56 if (($m != $_GET['m']) || !$c) {
57 header('HTTP/1.1 404 Not Found');
58 echo 'Document not found.';
65 if (isset($_REQUEST['to_a4a'])){
68 // require_once(TR_INCLUDE_PATH.'vitals.inc.php');
69 // $course_id = $_SESSION['course_id'];
71 //load the following after vitals is included
72 require_once(TR_INCLUDE_PATH.'classes/testQuestions.class.php');
73 require_once(TR_INCLUDE_PATH.'classes/A4a/A4aExport.class.php');
74 require_once(TR_INCLUDE_PATH.'classes/Weblinks/Weblinks.class.php');
75 require_once(TR_INCLUDE_PATH.'classes/Weblinks/WeblinksExport.class.php');
79 $coursesDAO = new CoursesDAO();
80 $course_row = $coursesDAO->get($course_id);
82 $contentManager = new ContentManager($course_id);
84 $instructor_id = $course_row['user_id'];
85 $course_desc = htmlspecialchars($course_row['description'], ENT_QUOTES, 'UTF-8');
86 $course_title = htmlspecialchars($course_row['title'], ENT_QUOTES, 'UTF-8');
87 $course_language = $course_row['primary_language'];
89 $courseLanguage =& $languageManager->getLanguage($course_language);
91 //If course language cannot be found, use UTF-8 English
92 //@author harris, Oct 30,2008
93 if (!isset($courseLanguage) || $courseLanguage == null){
94 $courseLanguage =& $languageManager->getLanguage(DEFAULT_LANGUAGE_CODE);
97 $course_language_charset = $courseLanguage->getCharacterSet();
98 $course_language_code = $courseLanguage->getCode();
100 require_once(TR_INCLUDE_PATH.'classes/zipfile.class.php'); /* for zipfile */
101 require_once(TR_INCLUDE_PATH.'classes/vcard.php'); /* for vcard */
102 require_once(TR_INCLUDE_PATH.'classes/XML/XML_HTMLSax/XML_HTMLSax.php'); /* for XML_HTMLSax */
103 require_once(TR_INCLUDE_PATH.'../home/imscc/include/ims_template.inc.php'); /* for ims templates + print_organizations() */
105 if (isset($_POST['cancel'])) {
106 $msg->addFeedback('EXPORT_CANCELLED');
107 header('Location: ../index.php');
111 $zipfile = new zipfile();
112 $zipfile->create_dir('resources/');
115 the following resources are to be identified:
116 even if some of these can't be images, they can still be files in the content dir.
117 theoretically the only urls we wouldn't deal with would be for a <!DOCTYPE and <form>
120 a => href // ignore if href doesn't exist (ie. <a name>)
121 object => data | classid // probably only want data
122 applet => classid | archive // whatever these two are should double check to see if it's a valid file (not a dir)
131 function MyHandler(){}
132 function openHandler(& $parser,$name,$attrs) {
135 $name = strtolower($name);
136 $attrs = array_change_key_case($attrs, CASE_LOWER);
138 $elements = array( 'img' => 'src',
140 'object' => array('data', 'classid'),
141 'applet' => array('classid', 'archive'),
150 /* check if this attribute specifies the files in different ways: (ie. java) */
151 if (is_array($elements[$name])) {
152 $items = $elements[$name];
154 foreach ($items as $item) {
155 if ($attrs[$item] != '') {
157 /* some attributes allow a listing of files to include seperated by commas (ie. applet->archive). */
158 if (strpos($attrs[$item], ',') !== false) {
159 $files = explode(',', $attrs[$item]);
160 foreach ($files as $file) {
161 $my_files[] = trim($file);
164 $my_files[] = $attrs[$item];
168 } else if (isset($elements[$name]) && ($attrs[$elements[$name]] != '')) {
169 //hack, if param[name]=src or none <param> tag, extract. Skip all other <param> attributes.
170 if ($name!='param' || $attrs['name']=='src'){
171 //skip glossary.html, tweak to accomodate atutor imscp; also skip repeated entries.
172 //skip javascript: links, void();, #, mailto:
173 if (strpos($attrs[$elements[$name]], 'glossary.html')===false
174 && !in_array($attrs[$elements[$name]], $my_files)
175 && $attrs[$elements[$name]]!='#'
176 && strpos($attrs[$elements[$name]], 'javascript:')===false
177 && strpos($attrs[$elements[$name]], 'mailto:')===false
178 && strpos($attrs[$elements[$name]], 'void(')===false
180 $my_files[] = $attrs[$elements[$name]];
185 function closeHandler(& $parser,$name) { }
188 /* get all the content */
191 $top_content_parent_id = 0;
193 $handler=new MyHandler();
194 $parser = new XML_HTMLSax();
195 $parser->set_object($handler);
196 $parser->set_element_handler('openHandler','closeHandler');
198 $contentDAO = new ContentDAO();
199 $rows = $contentDAO->getContentByCourseID($course_id);
201 //if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN)) {
202 // $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
204 // $sql = "SELECT *, UNIX_TIMESTAMP(last_modified) AS u_ts FROM ".TABLE_PREFIX."content WHERE course_id=$course_id ORDER BY content_parent_id, ordering";
206 //$result = mysql_query($sql, $db);
208 //$cid = $_REQUEST['cid']; //takes care of some system which lost the REQUEST[cid]
209 //while ($row = mysql_fetch_assoc($result)) {
210 // if (authenticate(TR_PRIV_CONTENT, TR_PRIV_RETURN) || $contentManager->isReleased($row['content_id']) === TRUE) {
211 if (is_array($rows)) {
212 foreach ($rows as $row) {
213 $content[$row['content_parent_id']][] = $row;
214 if ($cid == $row['content_id']) {
216 $top_content_parent_id = $row['content_parent_id'];
222 /* filter out the top level sections that we don't want */
223 $top_level = $content[$top_content_parent_id];
224 foreach($top_level as $page) {
225 if ($page['content_id'] == $cid) {
226 $content[$top_content_parent_id] = array($page);
228 /* this is a page we don't want, so might as well remove it's children too */
229 unset($content[$page['content_id']]);
232 $ims_course_title = $course_title . ' - ' . $content[$top_content_parent_id][0]['title'];
234 $ims_course_title = $course_title;
237 $imsmanifest_xml = str_replace(array('{COURSE_TITLE}', '{COURSE_DESCRIPTION}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}'),
238 array($ims_course_title, $course_desc, $course_language_charset, $course_language_code),
239 $ims_template_xml['header']);
240 //debug($imsmanifest_xml);
243 /* get the first content page to default the body frame to */
244 $first = $content[$top_content_parent_id][0];
246 $test_ids = array(); //global array to store all the test ids
248 // Modified by Cindy Qi Li on Jan 12, 2010
249 //AContent does not support glossary
250 //TODO**************BOLOGNA***************REMOVE ME***************************/
254 $forum_list = array();
256 // generate the resources and save the HTML files
257 $used_glossary_terms = array();
259 print_organizations($top_content_parent_id, $content, 0, '', array(), $toc_html);
262 print_resources_forum();
264 $organizations_str = ob_get_contents();
266 if (count($used_glossary_terms)) {
267 $used_glossary_terms = array_unique($used_glossary_terms);
268 sort($used_glossary_terms);
269 reset($used_glossary_terms);
271 foreach ($used_glossary_terms as $term) {
272 $term_key = htmlspecialchars($term, ENT_QUOTES, 'UTF-8');
273 $glossary[$term_key] = htmlentities($glossary[$term_key], ENT_QUOTES, 'UTF-8');
274 $glossary[$term_key] = str_replace('&', '&', $glossary[$term_key]);
275 $terms_xml .= str_replace( array('{TERM}', '{DEFINITION}'),
276 array($term_key, $glossary[$term_key]),
279 $glossary_xml = str_replace(array('{GLOSSARY_TERMS}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}'),
280 array($terms_xml, $course_language_charset),
283 $resources .= $ims_template_xml['resource_glossary'];
285 unset($glossary_xml);
289 $glossary_manifest_xml = $ims_template_xml['glossary'];
291 $glossary_manifest_xml = '';
296 print_organizations($top_content_parent_id, $content, 0, '', array(), $toc_html);
299 print_resources_forum();
301 $organizations_str = ob_get_contents();
303 // end of modified by Cindy Qi Li on Jan 12, 2010
305 /* append the Organizations and Resources to the imsmanifest */
306 $imsmanifest_xml .= str_replace( array('{ORGANIZATIONS}', '{GLOSSARY}', '{RESOURCES}', '{TEST_ITEMS}', '{COURSE_TITLE}'),
307 array($organizations_str, $glossary_manifest_xml, $resources, $test_xml_items, $ims_course_title),
308 $ims_template_xml['final']);
310 // generate the vcard for the instructor/author
311 $usersDAO = new UsersDAO();
312 $row = $usersDAO->getUserByID($instructor_id);
313 //$sql = "SELECT first_name, last_name, email, website, login, phone FROM ".TABLE_PREFIX."members WHERE member_id=$instructor_id";
314 //$result = mysql_query($sql, $db);
315 $vcard = new vCard();
317 $vcard->setName($row['last_name'], $row['first_name'], $row['login']);
318 $vcard->setEmail($row['email']);
319 $vcard->setNote('Originated from an AContent at '.TR_BASE_HREF.'. See ATutor.ca for additional information.');
320 $vcard->setURL($row['website']);
322 $imsmanifest_xml = str_replace('{VCARD}', $vcard->getVCard(), $imsmanifest_xml);
324 $imsmanifest_xml = str_replace('{VCARD}', '', $imsmanifest_xml);
327 /* save the imsmanifest.xml file */
328 $zipfile->add_file($imsmanifest_xml, 'imsmanifest.xml');
330 /* Commented by Cindy Qi Li on Jan 12, 2010
331 // AContent does not have glossary and forums (discussion tools)
333 $zipfile->create_dir('resources/GlossaryItem/');
334 $zipfile->add_file($glossary_xml, 'resources/GlossaryItem/glossary.xml');
338 $zipfile->close(); // this is optional, since send_file() closes it anyway
340 $ims_course_title = str_replace(array(' ', ':'), '_', $ims_course_title);
342 * A problem here with the preg_replace below.
343 * Originally was designed to remove all werid symbols to avoid file corruptions.
344 * In UTF-8, all non-english chars are considered to be 'werid symbols'
345 * We can still replace it as is, or add fileid to the filename to avoid these problems
346 * Well then again people won't be able to tell what this file is about
347 * If we are going to take out the preg_replace, some OS might not be able to understand
348 * these characters and will have problems importing.
350 $ims_course_title = preg_replace("{[^a-zA-Z0-9._-]}","", trim($ims_course_title));
351 $zipfile->send_file($ims_course_title . '_imscc');