2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2002 - 2009 */
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 /************************************************************************/
14 if (!defined('AT_INCLUDE_PATH')) { exit; }
16 // This function gets files from html tag @import
17 function get_import_files($text)
19 $text = strtolower($text);
23 while (strpos(strtolower($text), strtolower($tag)) > 0)
25 $start_pos = strpos($text, $tag);
26 if ($start_pos !== false)
28 $text = substr($text, $start_pos);
29 $start_pos = strlen($tag);
30 $len = strpos($text, ';') - strlen($tag);
32 $file = substr(trim($text), $start_pos, $len);
34 // remove these characters from file name: url, (, ), ", '
35 $file = trim(preg_replace('/(\'|\"|url|\(|\))/', '', $file));
37 // strip processed tag
38 $text = substr($text, $start_pos);
39 array_push($files, $file);
47 function print_organizations($parent_id,
54 global $html_content_template, $default_html_style, $zipfile, $resources, $ims_template_xml, $parser, $my_files;
55 global $used_glossary_terms, $course_id, $course_language_charset, $course_language_code;
56 static $paths, $zipped_files;
58 global $test_zipped_files, $use_a4a, $db;
66 $top_level = $_menu[$parent_id];
67 if (!is_array($paths)) {
70 if (!is_array($zipped_files)) {
71 $zipped_files = array();
73 if ( is_array($top_level) ) {
76 $num_items = count($top_level);
78 foreach ($top_level as $garbage => $content) {
81 if ($content['content_path']) {
82 $content['content_path'] .= '/';
84 //if this is a folder, export it without identifierref
85 if ($content['content_type']==CONTENT_TYPE_FOLDER){
86 $link = $prevfix.'<item identifier="MANIFEST01_ITEM'.$content['content_id'].'">'."\n";
88 $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";
90 $html_link = '<a href="resources/'.$content['content_path'].$content['content_id'].'.html" target="body">'.$content['title'].'</a>';
92 /* save the content as HTML files */
93 /* @See: include/lib/format_content.inc.php */
94 $content['text'] = str_replace('CONTENT_DIR/', '', $content['text']);
95 /* get all the glossary terms used */
96 $terms = find_terms($content['text']);
97 if (is_array($terms)) {
98 foreach ($terms[2] as $term) {
99 $used_glossary_terms[] = $term;
103 /** Test dependency **/
104 $test_dependency = ''; //Template for test
105 $sql = 'SELECT * FROM '.TABLE_PREFIX.'content_tests_assoc WHERE content_id='.$content['content_id'];
106 $result = mysql_query($sql, $db);
107 while ($row = mysql_fetch_assoc($result)){
108 //add test dependency ontop to forums dependency
109 $test_dependency .= $prefix.$space.'<dependency identifierref="MANIFEST01_RESOURCE_QTI'.$row['test_id'].'" />';
112 /* calculate how deep this page is: */
114 if ($content['content_path']) {
115 $depth = substr_count($content['content_path'], '/');
117 $path .= str_repeat('../', $depth);
120 $content['text'] = format_content($content['text'], $content['formatting'], $glossary, $path);
122 /* add HTML header and footers to the files */
124 /* use default style if <style> is not in imported html head */
126 if ($content['use_customized_head'])
128 if (strpos(strtolower($content['head']), '<style') > 0)
130 $head = $content['head'];
134 if (strlen($content['head']) > 0)
135 $head = $content['head'] . $default_html_style;
137 $head = $default_html_style;
141 $content['text'] = str_replace( array('{TITLE}', '{CONTENT}', '{KEYWORDS}', '{COURSE_PRIMARY_LANGUAGE_CHARSET}', '{COURSE_PRIMARY_LANGUAGE_CODE}', '{HEAD}'),
142 array($content['title'], $content['text'], $content['keywords'], $course_language_charset, $course_language_code, $head),
143 $html_content_template);
145 /* duplicate the paths in the content_path field in the zip file */
146 if ($content['content_path']) {
147 if (!in_array($content['content_path'], $paths)) {
148 $zipfile->create_dir('resources/'.$content['content_path'], time());
149 $paths[] = $content['content_path'];
153 $zipfile->add_file($content['text'], 'resources/'.$content['content_path'].$content['content_id'].'.html', $content['u_ts']);
154 $content['title'] = htmlspecialchars($content['title']);
156 /* add the resource dependancies */
157 if ($my_files == null) $my_files = array();
158 $content_files = "\n";
159 $parser->parse($content['text']);
161 /* generate the IMS QTI resource and files */
162 global $contentManager;
163 //check if test export is allowed.
164 if ($contentManager->allowTestExport($content['content_id'])){
165 $content_test_rs = $contentManager->getContentTestsAssoc($content['content_id']);
166 $test_ids = array(); //reset test ids
167 //$my_files = array(); //reset myfiles.
168 while ($content_test_row = mysql_fetch_assoc($content_test_rs)){
170 $test_ids[] = $content_test_row['test_id'];
171 //the 'added_files' is for adding into the manifest file in this zip
172 $added_files = test_qti_export($content_test_row['test_id'], '', $zipfile);
174 //Save all the xml files in this array, and then print_organizations will add it to the manifest file.
175 foreach($added_files as $filename=>$file_array){
176 $my_files[] = $filename;
177 foreach ($file_array as $garbage=>$filename2){
178 if (!in_array($filename2, $my_files)){
179 $my_files[] = $filename2;
184 //Save all the xml files in this array, and then print_organizations will add it to the manifest file.
185 $resources .= str_replace( array('{TEST_ID}', '{PATH}', '{FILES}'),
186 array($content_test_row['test_id'], 'tests_'.$content_test_row['test_id'].'.xml', $added_files_xml),
187 $ims_template_xml['resource_test']);
191 /* generate the a4a files */
192 $a4a_xml_array = array();
193 //http://atutor.ca/atutor/mantis/view.php?id=4593
194 if ($content['formatting']===0){
197 if ($use_a4a == true){
198 $a4aExport = new A4aExport($content['content_id']);
199 // $a4aExport->setRelativePath('resources/'.$content['content_path']);
200 $secondary_files = $a4aExport->getAllSecondaryFiles();
201 $a4a_xml_array = $a4aExport->exportA4a();
202 $my_files = array_merge($my_files, $a4aExport->getAllSecondaryFiles());
206 $import_files = get_import_files($content['text']);
208 if (count($import_files) > 0) $my_files = array_merge($my_files, $import_files);
210 foreach ($my_files as $file) {
211 /* filter out full urls */
212 $url_parts = @parse_url($file);
213 if (isset($url_parts['scheme'])) {
217 /* file should be relative to content. let's double check */
218 if ((substr($file, 0, 1) == '/')) {
222 $file_path = realpath(AT_CONTENT_DIR . $course_id . '/' . $content['content_path'] . $file);
224 /* check if this file exists in the content dir, if not don't include it */
225 if (file_exists($file_path) && is_file($file_path) && !in_array($file_path, $zipped_files)) {
226 $zipped_files[] = $file_path;
227 $dir = substr(dirname($file_path), strlen(AT_CONTENT_DIR . $course_id));
229 if (!in_array($dir, $paths) && $dir) {
230 $dir = str_replace('\\', '/', substr($dir, 1));
231 $zipfile->create_dir('resources/' . $dir, time());
236 $file_info = stat( $file_path );
238 //Fixes relative paths, so folder1/folder2/../file.jpg will become just folder1/file.jpg
239 $file_save_path = str_replace(AT_CONTENT_DIR . $course_id . DIRECTORY_SEPARATOR, '', $file_path);
240 $file_save_path = str_replace('\\', '/', $file_save_path);
242 //condition checks if the file has been added, so then the test won't be added to all the subchildren
243 //leads to normal images not capable to be extracted.
244 if ( (empty($test_zipped_files) || (is_array($test_zipped_files) && !in_array($file_path, $test_zipped_files)))
245 && file_exists($file_path)){
246 $zipfile->add_file(@file_get_contents($file_path), 'resources/' . $file_save_path, $file_info['mtime']);
247 // $test_zipped_files[] = $content['content_path'] . $file;
248 $test_zipped_files[] = $file_path;
249 } elseif (!is_array($test_zipped_files) && file_exists($file_path) && !in_array($file_path, $zipped_files)){
250 $zipfile->add_file(@file_get_contents($file_path), 'resources/' . $file_save_path, $file_info['mtime']);
253 //a4a secondary files have mapping, save the ones that we want in order to add the tag in
254 $a4a_secondary_files = array();
255 foreach ($a4a_xml_array as $a4a_filename=>$a4a_filearray){
256 if (preg_match('/(.*)\sto\s(.*)/', $a4a_filename, $matches)){
257 //save the actual file name
258 $a4a_secondary_files[$matches[1]][] = $a4a_filename; //values are holders
262 // If this file has a4a alternatives, link it.
263 if (isset($a4a_xml_array[$file]) || isset($a4a_secondary_files[$file])){
264 //if this is an array, meaning that it has more than 1 alternatives, print all
265 if (is_array($a4a_secondary_files[$file])){
266 $all_secondary_files_md = ''; //reinitialize string to null
267 foreach ($a4a_secondary_files[$file] as $v){
268 foreach($a4a_xml_array[$v] as $v2){
269 $all_secondary_files_md .= $v2; //all the meta data
272 $content_files .= str_replace( array('{FILE}', '{FILE_META_DATA}'),
273 array('resources/'.$file_save_path, $all_secondary_files_md),
274 $ims_template_xml['file_meta']);
276 $content_files .= str_replace( array('{FILE}', '{FILE_META_DATA}'),
277 array('resources/'.$file_save_path, $a4a_xml_array[$file]),
278 $ims_template_xml['file_meta']);
281 //if this file is in the test array, add an extra link to the direct file,
282 if (!empty($test_zipped_files) && in_array($file_path, $test_zipped_files)){
283 $content_files .= str_replace('{FILE}', $file_save_path, $ims_template_xml['file']);
285 $content_files .= str_replace('{FILE}', $file_save_path, $ims_template_xml['file']);
290 /* check if this file is one of the test xml file, if so, we need to add the dependency
291 * Note: The file has already been added to the archieve before this is called.
293 /* taken out as of nov 17th, used dependency instead
294 if (preg_match('/tests\_[0-9]+\.xml$/', $file) && !in_array($file, $test_zipped_files)){
295 $content_files .= str_replace('{FILE}', $file, $ims_template_xml['xml']);
296 $test_zipped_files[] = $file;
301 /******************************/
302 $resources .= str_replace( array('{CONTENT_ID}', '{PATH}', '{FILES}', '{DEPENDENCY}'),
303 array($content['content_id'], $content['content_path'], $content_files, $test_dependency),
304 $ims_template_xml['resource']);
307 for ($i=0; $i<$depth; $i++) {
311 $title = $prefix.$space.'<title>'.$content['title'].'</title>';
313 if ( is_array($_menu[$content['content_id']]) ) {
316 $html_link = '<li>'.$html_link.'<ul>';
317 for ($i=0; $i<$depth; $i++) {
318 if ($children[$i] == 1) {
320 //$html_link = $space.$html_link;
323 //$html_link = $space.$html_link;
328 /* doesn't have children */
330 $html_link = '<li>'.$html_link.'</li>';
331 if ($counter == $num_items) {
332 for ($i=0; $i<$depth; $i++) {
333 if ($children[$i] == 1) {
335 //$html_link = $space.$html_link;
338 //$html_link = $space.$html_link;
342 for ($i=0; $i<$depth; $i++) {
344 //$html_link = $space.$html_link;
347 $title = $space.$title;
354 $string .= $html_link."\n";
357 print_organizations($content['content_id'],
366 for ($i=0; $i<$depth; $i++) {
369 echo $prefix.'</item>';
381 $ims_template_xml['header'] = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
382 <!--This is an ATutor SCORM 1.2 Content Package document-->
383 <!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
384 <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()).'"
385 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"
386 version = "CP 1.1.4">
388 <schema>ADL SCORM</schema>
389 <schemaversion>1.2</schemaversion>
393 <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_TITLE}</imsmd:langstring>
396 <imsmd:langstring xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}">{COURSE_DESCRIPTION}</imsmd:langstring>
403 <imsmd:langstring xml:lang="x-none">LOMv1.0</imsmd:langstring>
406 <imsmd:langstring xml:lang="x-none">Author</imsmd:langstring>
410 <imsmd:vcard>{VCARD}</imsmd:vcard>
415 <imsmd:learningresourcetype>
417 <imsmd:langstring xml:lang="x-none">ATutor</imsmd:langstring>
420 <imsmd:langstring xml:lang="x-none">Content Module</imsmd:langstring>
422 </imsmd:learningresourcetype>
430 $ims_template_xml['resource'] = ' <resource identifier="MANIFEST01_RESOURCE{CONTENT_ID}" type="webcontent" href="resources/{PATH}{CONTENT_ID}.html" adlcp:scormtype="asset">
432 <file href="resources/{PATH}{CONTENT_ID}.html"/>{FILES}
436 $ims_template_xml['resource_test'] = ' <resource identifier="MANIFEST01_RESOURCE_QTI{TEST_ID}" type="imsqti_xmlv1p2/imscc_xmlv1p0/assessment">
438 <file href="{PATH}"/>{FILES}
442 $ims_template_xml['file'] = ' <file href="resources/{FILE}"/>'."\n";
443 $ims_template_xml['xml'] = ' <file href="{FILE}"/>'."\n";
444 $ims_template_xml['file_meta'] = ' <file href="{FILE}">
449 $ims_template_xml['final'] = '
450 <organizations default="MANIFEST01_ORG1">
451 <organization identifier="MANIFEST01_ORG1" structure="hierarchical">
452 <title>{COURSE_TITLE}</title>
461 $html_template = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
462 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
463 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
465 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
466 <style type="text/css">
467 body { font-family: Verdana, Arial, Helvetica, sans-serif;}
468 a.at-term { font-style: italic; }
470 <title>{TITLE}</title>
471 <meta name="Generator" content="ATutor">
472 <meta name="Keywords" content="{KEYWORDS}">
474 <body>{CONTENT}</body>
477 $html_content_template = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
478 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
479 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
481 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
483 <title>{TITLE}</title>
484 <meta name="Generator" content="ATutor">
485 <meta name="Keywords" content="{KEYWORDS}">
487 <body>{CONTENT}</body>
490 $default_html_style = ' <style type="text/css">
491 body { font-family: Verdana, Arial, Helvetica, sans-serif;}
492 a.at-term { font-style: italic; }
495 //output this as header.html
496 $html_mainheader = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
497 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
498 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
500 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
501 <link rel="stylesheet" type="text/css" href="ims.css"/>
502 <title>{COURSE_TITLE}</title>
504 <body class="headerbody"><h3>{COURSE_TITLE}</h3></body></html>';
507 $html_toc = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
508 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
509 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
511 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
512 <link rel="stylesheet" type="text/css" href="ims.css" />
515 <body>{TOC}</body></html>';
518 $html_frame = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
519 "http://www.w3.org/TR/html4/frameset.dtd">
520 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
521 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
522 <title>{COURSE_TITLE}</title>
524 <frameset rows="50,*,50">
525 <frame src="header.html" name="header" title="header" scrolling="no">
526 <frameset cols="25%, *" frameborder="1" framespacing="3">
527 <frame frameborder="2" marginwidth="0" marginheight="0" src="toc.html" name="frame" title="TOC">
528 <frame frameborder="2" src="resources/{PATH}{FIRST_ID}.html" name="body" title="{COURSE_TITLE}">
530 <frame src="footer.html" name="footer" title="footer" scrolling="no">
532 <h1>{COURSE_TITLE}</h1>
533 <p><a href="toc.html">Table of Contents</a> | <a href="footer.html">About</a><br />
540 $footer_html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
541 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
542 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{COURSE_PRIMARY_LANGUAGE_CODE}" lang="{COURSE_PRIMARY_LANGUAGE_CODE}">
544 <link rel="stylesheet" type="text/css" href="ims.css" />
545 <title>{CONTENT_PACKAGE_TITLE}</title>
546 <meta http-equiv="Content-Type" content="text/html; charset={COURSE_PRIMARY_LANGUAGE_CHARSET}" />
548 <body class="footerbody">
551 <td valign="middle" align="left"><a href="http://www.atutor.ca" target="_blank"><img src="logo.gif" border="0" alt="ATutor.ca - opens in a new window" width="84" height="29" align="left" title="ATutor.ca - opens in a new window" /></a></td>
552 <td><span class="footer">{CONTENT_PACKAGE_HOW_TO}</span></td>
558 $glossary_xml = '<?xml version="1.0" encoding="{COURSE_PRIMARY_LANGUAGE_CHARSET}"?>
559 <!--This is an ATutor Glossary terms document-->
560 <!--Created from the ATutor Content Package Generator - http://www.atutor.ca-->
563 <!ELEMENT item (term, definition)>
564 <!ELEMENT term (#PCDATA)>
565 <!ELEMENT definition (#PCDATA)>
573 $glossary_term_xml = ' <item>
575 <definition>{DEFINITION}</definition>
578 $glossary_body_html = '<h2>Glossary</h2>
583 $glossary_term_html = ' <li><a name="{ENCODED_TERM}"></a><strong>{TERM}</strong><br />
584 {DEFINITION}<br /><br /></li>';