2 /************************************************************************/
\r
4 /************************************************************************/
\r
5 /* Copyright (c) 2010 */
\r
6 /* Inclusive Design Institute */
\r
8 /* This program is free software. You can redistribute it and/or */
\r
9 /* modify it under the terms of the GNU General Public License */
\r
10 /* as published by the Free Software Foundation. */
\r
11 /************************************************************************/
\r
14 * Content Utility functions
\r
16 * @author Cindy Qi Li
\r
19 if (!defined('TR_INCLUDE_PATH')) exit;
\r
21 class ContentUtility {
\r
24 * This function cuts out html body
\r
26 * @param $text html text
\r
27 * @author Cindy Qi Li
\r
29 public static function getHtmlBody($text) {
\r
30 /* strip everything before <body> */
\r
31 $start_pos = strpos(strtolower($text), '<body');
\r
32 if ($start_pos !== false) {
\r
33 $start_pos += strlen('<body');
\r
34 $end_pos = strpos(strtolower($text), '>', $start_pos);
\r
35 $end_pos += strlen('>');
\r
37 $text = substr($text, $end_pos);
\r
40 /* strip everything after </body> */
\r
41 $end_pos = strpos(strtolower($text), '</body>');
\r
42 if ($end_pos !== false) {
\r
43 $text = trim(substr($text, 0, $end_pos));
\r
50 * This function cuts out requested tag information from html head
\r
52 * @param $text html text
\r
53 * @param $tags a string or an array of requested tags
\r
54 * @author Cindy Qi Li
\r
56 public static function getHtmlHeadByTag($text, $tags)
\r
58 $head = ContentUtility::getHtmlHead($text);
\r
61 if (!is_array($tags) && strlen(trim($tags)) > 0)
\r
63 $tags = array(trim($tags));
\r
65 foreach ($tags as $tag)
\r
67 $tag = strtolower($tag);
\r
69 /* strip everything before <{tag}> */
\r
70 $start_pos = stripos($head, '<'.$tag);
\r
73 while ($start_pos !== false)
\r
75 $temp_text = substr($temp_head, $start_pos);
\r
77 /* strip everything after </{tag}> or />*/
\r
78 $end_pos = stripos($temp_text, '</' . $tag . '>');
\r
80 if ($end_pos !== false)
\r
82 $end_pos += strlen('</' . $tag . '>');
\r
84 // add an empty line after each tag information
\r
85 $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
\r
89 else // match /> as ending tag if </tag> is not found
\r
91 $end_pos = stripos($temp_text, '/>');
\r
93 if($end_pos === false && stripos($temp_text, $tag.'>')===false){
\r
94 //if /> is not found, then this is not a valid XHTML
\r
95 //text iff it's not tag>
\r
96 $end_pos = stripos($temp_text, '>');
\r
97 $end_pos += strlen('>');
\r
99 $end_pos += strlen('/>');
\r
101 // add an empty line after each tag information
\r
102 $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
\r
107 // initialize vars for next round of matching
\r
108 $temp_head = substr($temp_text, $end_pos);
\r
109 $start_pos = stripos($temp_head, '<'.$tag);
\r
116 * This function cuts out html head
\r
118 * @param $text html text
\r
119 * @author Cindy Qi Li
\r
121 private static function getHtmlHead ($text) {
\r
122 /* strip everything before <head> */
\r
123 $start_pos = stripos($text, '<head');
\r
124 if ($start_pos !== false) {
\r
125 $start_pos += strlen('<head');
\r
126 $end_pos = stripos($text, '>', $start_pos);
\r
127 $end_pos += strlen('>');
\r
129 $text = substr($text, $end_pos);
\r
132 /* strip everything after </head> */
\r
133 $end_pos = stripos($text, '</head');
\r
134 if ($end_pos !== false) {
\r
135 $text = trim(substr($text, 0, $end_pos));
\r
140 private static function embedFLV($text) {
\r
141 global $content_base_href;
\r
143 // .flv - uses Flowplayer 3.0 from flowplayer.org (playing file via full URL)
\r
144 preg_match_all("#\[media[0-9a-z\|]*\]http://([\w\./-]+)\.flv\[/media\]#i",$text,$media_matches[0],PREG_SET_ORDER);
\r
145 $media_replace[0] ="<a class=\"flowplayerholder\"
\r
146 style=\"display:block;width:##WIDTH##px;height:##HEIGHT##px;\"
\r
147 href=\"http://##MEDIA1##.flv\">
\r
150 // .flv - uses Flowplayer 3.0 from flowplayer.org (playing file from AT_content_dir)
\r
151 preg_match_all("#\[media[0-9a-z\|]*\]([\w\./-]+)\.flv\[/media\]#i",$text,$media_matches[1],PREG_SET_ORDER);
\r
152 $media_replace[1] ="<a class=\"flowplayerholder\"
\r
153 style=\"display:block;width:##WIDTH##px;height:##HEIGHT##px;\"
\r
154 href=\"".TR_BASE_HREF."get.php/".$content_base_href."##MEDIA1##.flv\">
\r
158 // Executing the replace
\r
159 for ($i=0;$i<count($media_replace);$i++){
\r
160 foreach($media_matches[$i] as $media)
\r
162 if (is_array($media)) $has_flv = true;
\r
164 //find width and height for each matched media
\r
165 if (preg_match("/\[media\|([0-9]*)\|([0-9]*)\]*/", $media[0], $matches))
\r
167 $width = $matches[1];
\r
168 $height = $matches[2];
\r
176 //replace media tags with embedded media for each media tag
\r
177 $media_input = $media_replace[$i];
\r
178 $media_input = str_replace("##WIDTH##","$width",$media_input);
\r
179 $media_input = str_replace("##HEIGHT##","$height",$media_input);
\r
180 $media_input = str_replace("##MEDIA1##","$media[1]",$media_input);
\r
181 $media_input = str_replace("##MEDIA2##","$media[2]",$media_input);
\r
182 $text = str_replace($media[0],$media_input,$text);
\r
189 <script language="JavaScript">
\r
190 $f("a.flowplayerholder", "'.TR_BASE_HREF.'include/jscripts/flowplayer/flowplayer-3.2.5.swf", {
\r
191 clip: { autoPlay: false },
\r
207 public static function embedMedia($text) {
\r
208 if (preg_match("/\[media(\|[0-9]+\|[0-9]+)?\]*/", $text)==0){
\r
212 // remove the spaces in [media] tag, otherwise, the next line converts URL inside [media] into <a> tag
\r
213 $text = preg_replace("/(\[media\])([\s]*)(.*)(\[\/media\])/", '$1$3$4', $text);
\r
214 $text = preg_replace("/(\[media\])(.*)([\s]*)(\[\/media\])/U", '$1$2$4', $text);
\r
216 $media_matches = Array();
\r
219 First, we search though the text for all different kinds of media defined by media tags and store the results in $media_matches.
\r
221 Then the different replacements for the different media tags are stored in $media_replace.
\r
223 Lastly, we loop through all $media_matches / $media_replaces. (We choose $media_replace as index because $media_matches is multi-dimensioned.) It is important that for each $media_matches there is a $media_replace with the same index. For each media match we check the width/height, or we use the default value of 425x350. We then replace the height/width/media1/media2 parameter placeholders in $media_replace with the correct ones, before running a str_replace on $text, replacing the given media with its correct replacement.
\r
228 preg_match_all("#\[media[0-9a-z\|]*\]http://([a-z0-9\.]*)?youtube.com/watch\?v=([a-z0-9_-]+)\[/media\]#i",$text,$media_matches[1],PREG_SET_ORDER);
\r
229 $media_replace[1] = '<object width="##WIDTH##" height="##HEIGHT##"><param name="movie" value="http://##MEDIA1##youtube.com/v/##MEDIA2##"></param><embed src="http://##MEDIA1##youtube.com/v/##MEDIA2##" type="application/x-shockwave-flash" width="##WIDTH##" height="##HEIGHT##"></embed></object>';
\r
232 preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mpg\[/media\]#i",$text,$media_matches[2],PREG_SET_ORDER);
\r
233 $media_replace[2] = "<object data=\"##MEDIA1##.mpg\" type=\"video/mpeg\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mpg\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.mpg\">##MEDIA1##.mpg</a></object>";
\r
236 preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).avi\[/media\]#i",$text,$media_matches[3],PREG_SET_ORDER);
\r
237 $media_replace[3] = "<object data=\"##MEDIA1##.avi\" type=\"video/x-msvideo\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.avi\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.avi\">##MEDIA1##.avi</a></object>";
\r
240 preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).wmv\[/media\]#i",$text,$media_matches[4],PREG_SET_ORDER);
\r
241 $media_replace[4] = "<object data=\"##MEDIA1##.wmv\" type=\"video/x-ms-wmv\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.wmv\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.wmv\">##MEDIA1##.wmv</a></object>";
\r
244 preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mov\[/media\]#i",$text,$media_matches[5],PREG_SET_ORDER);
\r
245 $media_replace[5] = "<object classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\" codebase=\"http://www.apple.com/qtactivex/qtplugin.cab\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mov\"><param name=\"controller\" value=\"true\"><param name=\"autoplay\" value=\"false\"><!--[if gte IE 7]> <!--><object type=\"video/quicktime\" data=\"##MEDIA1##.mov\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"controller\" value=\"true\"><param name=\"autoplay\" value=\"false\"><a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a></object><!--<![endif]--><!--[if lt IE 7]><a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a><![endif]--></object>";
\r
248 preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).swf\[/media\]#i",$text,$media_matches[6],PREG_SET_ORDER);
\r
249 $media_replace[6] = "<object type=\"application/x-shockwave-flash\" data=\"##MEDIA1##.swf\" width=\"##WIDTH##\" height=\"##HEIGHT##\"> <param name=\"movie\" value=\"##MEDIA1##.swf\"><param name=\"loop\" value=\"false\"><a href=\"##MEDIA1##.swf\">##MEDIA1##.swf</a></object>";
\r
252 preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mp3\[/media\]#i",$text,$media_matches[7],PREG_SET_ORDER);
\r
253 $media_replace[7] = "<object type=\"audio/mpeg\" data=\"##MEDIA1##.mp3\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mp3\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.mp3\">##MEDIA1##.mp3</a></object>";
\r
256 preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).wav\[/media\]#i",$text,$media_matches[8],PREG_SET_ORDER);
\r
257 $media_replace[8] ="<object type=\"audio/x-wav\" data=\"##MEDIA1##.wav\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.wav\"><param name=\"autoplay\" value=\"false\"><param name=\"autoStart\" value=\"0\"><a href=\"##MEDIA1##.wav\">##MEDIA1##.wav</a></object>";
\r
260 preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).ogg\[/media\]#i",$text,$media_matches[9],PREG_SET_ORDER);
\r
261 $media_replace[9] ="<object type=\"application/ogg\" data=\"##MEDIA1##.ogg\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.ogg\"><a href=\"##MEDIA1##.ogg\">##MEDIA1##.ogg</a></object>";
\r
264 preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mid\[/media\]#i",$text,$media_matches[10],PREG_SET_ORDER);
\r
265 $media_replace[10] ="<object type=\"application/x-midi\" data=\"##MEDIA1##.mid\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.mid\"><a href=\"##MEDIA1##.mid\">##MEDIA1##.mid</a></object>";
\r
267 $text = preg_replace("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mid\[/media\]#i", "<object type=\"application/x-midi\" data=\"\\1.mid\" width=\"".$width."\" height=\"".$height."\"><param name=\"src\" value=\"\\1.mid\"><a href=\"\\1.mid\">\\1.mid</a></object>", $text);
\r
269 // Executing the replace
\r
270 for ($i=1;$i<=count($media_replace);$i++){
\r
271 foreach($media_matches[$i] as $media)
\r
274 //find width and height for each matched media
\r
275 if (preg_match("/\[media\|([0-9]*)\|([0-9]*)\]*/", $media[0], $matches))
\r
277 $width = $matches[1];
\r
278 $height = $matches[2];
\r
286 //replace media tags with embedded media for each media tag
\r
287 $media_input = $media_replace[$i];
\r
288 $media_input = str_replace("##WIDTH##","$width",$media_input);
\r
289 $media_input = str_replace("##HEIGHT##","$height",$media_input);
\r
290 $media_input = str_replace("##MEDIA1##","$media[1]",$media_input);
\r
291 $media_input = str_replace("##MEDIA2##","$media[2]",$media_input);
\r
292 $text = str_replace($media[0],$media_input,$text);
\r
299 public static function makeClickable($text) {
\r
300 $text = ContentUtility::embedMedia($text);
\r
302 // convert plain text URL to clickable URL.
\r
303 // Limited conversion: It doesn't cover the case when the stuff in front of the URL is not a word. For example:
\r
304 // <p>http://google.ca</p>
\r
305 // "http://google.ca"
\r
306 $text = preg_replace('/(^|[\n ])([\w]*?)((?<!(\[media\]))http(s)?:\/\/[\w]+[^ \,\"\n\r\t\)<]*)/is',
\r
307 '$1$2<a href="$3">$3</a>', $text);
\r
309 // convert email address to clickable URL that pops up "send email" interface with the address filled in
\r
310 $text = preg_replace('/(?|<a href="mailto[\s]*:[\s]*([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'\@'
\r
311 .'[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'(\.[a-zA-Z]{1,6})+)">(.*)<\/a>'
\r
312 .'|((((([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'\@'
\r
313 .'[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'(\.[a-zA-Z]{1,6})+))))))/i',
\r
314 "<a href=\"mailto:\\1\">\\5</a>",
\r
317 // flv conversion needs to come after url conversion (2 lines above) otherwise the url to flowplayer swf file
\r
318 // in the script for a.flowplayerholder is converted
\r
319 $text = ContentUtility::embedFLV($text);
\r
324 public static function myCodes($text, $html = false) {
\r
325 global $_base_path;
\r
326 global $HTTP_USER_AGENT;
\r
328 if (substr($HTTP_USER_AGENT,0,11) == 'Mozilla/4.7') {
\r
329 $text = str_replace('[quote]','</p><p class="block">',$text);
\r
330 $text = str_replace('[/quote]','</p><p>',$text);
\r
332 $text = str_replace('[reply]','</p><p class="block">',$text);
\r
333 $text = str_replace('[/reply]','</p><p>',$text);
\r
335 $text = str_replace('[quote]','<blockquote>',$text);
\r
336 $text = str_replace('[/quote]','</blockquote><p>',$text);
\r
338 $text = str_replace('[reply]','</p><blockquote class="block"><p>',$text);
\r
339 $text = str_replace('[/reply]','</p></blockquote><p>',$text);
\r
342 $text = str_replace('[b]','<strong>',$text);
\r
343 $text = str_replace('[/b]','</strong>',$text);
\r
345 $text = str_replace('[i]','<em>',$text);
\r
346 $text = str_replace('[/i]','</em>',$text);
\r
348 $text = str_replace('[u]','<u>',$text);
\r
349 $text = str_replace('[/u]','</u>',$text);
\r
351 $text = str_replace('[center]','<center>',$text);
\r
352 $text = str_replace('[/center]','</center><p>',$text);
\r
355 $text = str_replace('[blue]','<span style="color: blue;">',$text);
\r
356 $text = str_replace('[/blue]','</span>',$text);
\r
358 $text = str_replace('[orange]','<span style="color: orange;">',$text);
\r
359 $text = str_replace('[/orange]','</span>',$text);
\r
361 $text = str_replace('[red]','<span style="color: red;">',$text);
\r
362 $text = str_replace('[/red]','</span>',$text);
\r
364 $text = str_replace('[purple]','<span style="color: purple;">',$text);
\r
365 $text = str_replace('[/purple]','</span>',$text);
\r
367 $text = str_replace('[green]','<span style="color: green;">',$text);
\r
368 $text = str_replace('[/green]','</span>',$text);
\r
370 $text = str_replace('[gray]','<span style="color: gray;">',$text);
\r
371 $text = str_replace('[/gray]','</span>',$text);
\r
373 $text = str_replace('[op]','<span class="bigspacer"></span> <a href="',$text);
\r
374 $text = str_replace('[/op]','">'._AT('view_entire_post').'</a>',$text);
\r
376 $text = str_replace('[head1]','<h2>',$text);
\r
377 $text = str_replace('[/head1]','</h2>',$text);
\r
379 $text = str_replace('[head2]','<h3>',$text);
\r
380 $text = str_replace('[/head2]','</h3>',$text);
\r
382 $text = str_replace('[cid]',$_base_path.'content.php?_cid='.$_SESSION['s_cid'],$text);
\r
384 global $sequence_links, $_course_id, $_content_id;
\r
385 if ($_course_id > 0 && !isset($sequence_links) && $_content_id > 0) {
\r
386 global $contentManager;
\r
387 $sequence_links = $contentManager->generateSequenceCrumbs($_content_id);
\r
389 if (isset($sequence_links['previous']) && $sequence_links['previous']['url']) {
\r
390 $text = str_replace('[pid]', $sequence_links['previous']['url'], $text);
\r
392 if (isset($sequence_links['next']) && $sequence_links['next']['url']) {
\r
393 $text = str_replace('[nid]', $sequence_links['next']['url'], $text);
\r
395 if (isset($sequence_links['resume']) && $sequence_links['resume']['url']) {
\r
396 $text = str_replace('[nid]', $sequence_links['resume']['url'], $text);
\r
398 if (isset($sequence_links['first']) && $sequence_links['first']['url']) {
\r
399 $text = str_replace('[fid]', $sequence_links['first']['url'], $text);
\r
402 /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
\r
403 $html = !$html ? 0 : 1;
\r
405 // little hack added by greg to add syntax highlighting without using <?php \?\>
\r
407 $text = str_replace("[code]","[code]<?php",$text);
\r
408 $text = str_replace("[/code]","?>[/code]",$text);
\r
410 $text = preg_replace("/\[code\]\s*(.*)\s*\[\\/code\]/Usei", "ContentUtility::highlightCode(ContentUtility::fixQuotes('\\1'), $html)", $text);
\r
411 // now remove the <?php added above and leave the syntax colour behind.
\r
412 $text = str_replace("<?php", "", $text);
\r
413 $text = str_replace("?>", "", $text);
\r
418 /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
\r
419 private static function highlightCode($code, $html) {
\r
420 // XHTMLize PHP highlight_string output until it gets fixed in PHP
\r
421 static $search = array(
\r
427 static $replace = array(
\r
433 $code = str_replace('<', '<', $code);
\r
434 $code = str_replace("\r", '', $code);
\r
437 return str_replace($search, $replace, highlight_string($code, true));
\r
440 /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
\r
441 private static function fixQuotes($text){
\r
442 return str_replace('\\"', '"', $text);
\r
445 public static function imageReplace($text) {
\r
446 /* image urls do not require http:// */
\r
448 // $text = eregi_replace("\[image(\|)?([[:alnum:][:space:]]*)\]" .
\r
450 // "([[:alnum:]#?/&=:\"'_.-]+)" .
\r
452 // "((\[/image\])|(.*\[/image\]))",
\r
453 // "<img src=\"\\3\" alt=\"\\2\" />",
\r
456 $text = preg_replace("/\[image(\|)?([a-zA-Z0-9\s]*)\]".
\r
458 "([a-zA-Z0-9\#\?\/\&\=\:\\\"\'\_\.\-]+)[\s]*".
\r
459 "((\[\/image\])|(.*\[\/image\]))/i",
\r
460 "<img src=\"\\3\" alt=\"\\2\" />",
\r
466 private static function formatFinalOutput($text, $nl2br = true) {
\r
467 global $_base_path;
\r
469 $text = str_replace('CONTENT_DIR/', '', $text);
\r
471 return nl2br(ContentUtility::imageReplace(ContentUtility::makeClickable(ContentUtility::myCodes(' '.$text, false))));
\r
474 return ContentUtility::imageReplace(ContentUtility::makeClickable(ContentUtility::myCodes(' '.$text, true)));
\r
478 * This function converts the input string into AContent html content string
\r
480 * @param $input: input string
\r
481 * $html: whether the input is in html
\r
482 * @return converted AContent html content string
\r
483 * @author Cindy Qi Li
\r
485 public static function formatContent($input, $html = 0) {
\r
486 global $_base_path, $_config;
\r
489 $input = str_replace('<', '<', $input);
\r
490 $input = str_replace('<?php', '<?php', $input); // for bug #2087
\r
491 } elseif ($html==2) {
\r
492 $output = '<iframe width="100%" frameborder="0" id="content_frame" marginheight="0" marginwidth="0" src="'.$input.'"></iframe>';
\r
493 $output .= '<script type="text/javascript">
\r
494 function resizeIframe() {
\r
495 var height = document.documentElement.clientHeight;
\r
497 // not sure how to get this dynamically
\r
498 height -= 20; /* whatever you set your body bottom margin/padding to be */
\r
500 document.getElementById(\'content_frame\').style.height = height +"px";
\r
503 document.getElementById(\'content_frame\').onload = resizeIframe;
\r
504 window.onresize = resizeIframe;
\r
509 /* Commented by Cindy Qi Li on Jan 12, 2010
\r
510 * AContent does not support glossary
\r
511 // do the glossary search and replace:
\r
512 if (is_array($glossary)) {
\r
513 foreach ($glossary as $k => $v) {
\r
514 $k = urldecode($k);
\r
515 $v = str_replace("\n", '<br />', $v);
\r
516 $v = str_replace("\r", '', $v);
\r
518 // escape special characters
\r
519 $k = preg_quote($k);
\r
521 $k = str_replace('<', '<', $k);
\r
522 $k = str_replace('/', '\/', $k);
\r
524 $original_term = $k;
\r
525 $term = $original_term;
\r
527 $term = '(\s*'.$term.'\s*)';
\r
528 $term = str_replace(' ','((<br \/>)*\s*)', $term);
\r
530 $def = htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
\r
532 $input = preg_replace
\r
533 ("/(\[\?\])$term(\[\/\?\])/i",
\r
534 '<a href="'.$simple.'glossary.html#'.urlencode($original_term).'" target="body" class="at-term">\\2</a>',
\r
537 $input = preg_replace
\r
538 ("/(\[\?\])$term(\[\/\?\])/i",
\r
539 '\\2<sup><a class="tooltip" href="'.$_base_path.'glossary/index.php?g_cid='.$_SESSION['s_cid'].htmlentities(SEP).'w='.urlencode($original_term).'#term" title="'.addslashes($original_term).': '.$def.'"><span style="color: blue; text-decoration: none;font-size:small; font-weight:bolder;">?</span></a></sup>',$input);
\r
542 } else if (!$user_glossary) {
\r
543 $input = str_replace(array('[?]','[/?]'), '', $input);
\r
548 $input = str_replace('CONTENT_DIR', '', $input);
\r
550 if (isset($_config['latex_server']) && $_config['latex_server']) {
\r
551 // see: http://www.forkosh.com/mimetex.html
\r
552 $input = preg_replace('/\[tex\](.*?)\[\/tex\]/sie', "'<img src=\"'.\$_config['latex_server'].rawurlencode('$1').'\" align=\"middle\">'", $input);
\r
556 $x = ContentUtility::formatFinalOutput($input, false);
\r
560 $output = ContentUtility::formatFinalOutput($input);
\r
562 $output = '<p>'.$input.'</p>';
\r
568 * This function returns html string of "table of content"
\r
570 * @param: $content: a string
\r
571 * @return: a html string of "table of content"
\r
573 public static function getContentTable($content)
\r
575 preg_match_all("/<(h[\d]+)[^>]*>(.*)<\/(\s*)\\1(\s*)>/i", $content, $found_headers, PREG_SET_ORDER);
\r
577 if (count($found_headers) == 0) return array("", $content);
\r
580 $num_of_headers = 0;
\r
582 for ($i = 0; $i < count($found_headers); $i++)
\r
584 $div_id = "_header_" . $num_of_headers++;
\r
588 $content_table = "<div id=\"toc\">\n<fieldset id=\"toc\"><legend>". _AT("table_of_contents")."</legend>\n";
\r
591 $content = str_replace($found_headers[$i][0], '<div id="'.$div_id.'">'.$found_headers[$i][0].'</div>', $content);
\r
592 $content_table .= '<a href="'.$_SERVER["REQUEST_URI"].'#'.$div_id.'" class="'.$found_headers[$i][1].'">'. $found_headers[$i][2]."</a>\n";
\r
594 if ($i == count($found_headers) - 1)
\r
596 $content_table .= "</fieldset></div><br />";
\r
599 return array($content_table, $content);
\r
604 * This function returns an array of content tools' shortcuts
\r
606 * @param: $content_row: an array of the current content information
\r
607 * @return: an array of all the tool short cuts that apply to the current content or content folder
\r
609 public static function getToolShortcuts($content_row)
\r
611 global $_current_user, $_base_href, $contentManager, $_course_id;
\r
613 if (((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
\r
614 || ($_SESSION['packaging'] == 'all'))
\r
615 || (isset($_current_user) && $_current_user->isAuthor($_course_id))) {
\r
617 $tool_shortcuts[] = array(
\r
618 'title' => _AT('export_content_in_cp'),
\r
619 'url' => $_base_href . 'home/ims/ims_export.php?_cid='.$content_row['content_id'],
\r
620 'icon' => $_base_href . 'themes/'.$_SESSION['prefs']['PREF_THEME'].'/images/export.png');
\r
621 $tool_shortcuts[] = array(
\r
622 'title' => _AT('export_content_in_cc'),
\r
623 'url' => $_base_href . 'home/imscc/ims_export.php?_cid='.$content_row['content_id'].SEP.'to_a4a=1',
\r
624 'icon' => $_base_href . 'themes/'.$_SESSION['prefs']['PREF_THEME'].'/images/export_cc.png');
\r
627 if (isset($_current_user) && $_current_user->isAuthor($_course_id)) {
\r
628 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
\r
629 $tool_shortcuts[] = array(
\r
630 'title' => _AT('edit_this_page'),
\r
631 'url' => $_base_href . 'home/editor/edit_content.php?_cid='.$content_row['content_id'],
\r
632 'icon' => $_base_href . 'images/medit.gif');
\r
635 $tool_shortcuts[] = array(
\r
636 'title' => _AT('add_sibling_folder'),
\r
637 'url' => $_base_href .
\r
638 'home/editor/edit_content_folder.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'].SEP.'_course_id='.$_course_id,
\r
639 'icon' => $_base_href . 'images/add_sibling_folder.gif');
\r
641 if ($content_row['content_type'] == CONTENT_TYPE_FOLDER || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
\r
642 $tool_shortcuts[] = array(
\r
643 'title' => _AT('add_sub_folder'),
\r
644 'url' => $_base_href .
\r
645 'home/editor/edit_content_folder.php?_course_id='.$_course_id.SEP.'pid='.$content_row['content_id'],
\r
646 'icon' => $_base_href . 'images/add_sub_folder.gif');
\r
649 $tool_shortcuts[] = array(
\r
650 'title' => _AT('add_sibling_page'),
\r
651 'url' => $_base_href .
\r
652 'home/editor/edit_content.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'].SEP.'_course_id='.$_course_id,
\r
653 'icon' => $_base_href . 'images/add_sibling_page.gif');
\r
655 if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
\r
656 $tool_shortcuts[] = array(
\r
657 'title' => _AT('delete_this_page'),
\r
658 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$content_row['content_id'],
\r
659 'icon' => $_base_href . 'images/page_delete.gif');
\r
661 else if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
\r
662 $tool_shortcuts[] = array(
\r
663 'title' => _AT('add_sub_page'),
\r
664 'url' => $_base_href . 'home/editor/edit_content.php?_course_id='.$_course_id.SEP.'pid='.$content_row['content_id'],
\r
665 'icon' => $_base_href . 'images/add_sub_page.gif');
\r
667 $tool_shortcuts[] = array(
\r
668 'title' => _AT('delete_this_folder'),
\r
669 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$content_row['content_id'],
\r
670 'icon' => $_base_href . 'images/page_delete.gif');
\r
673 return $tool_shortcuts;
\r
675 // if (isset($_current_user) && $_current_user->isAuthor($_course_id)) {
\r
676 // $shortcuts[] = array('title' => _AT('add_sub_folder'), 'url' => $_base_href . 'home/editor/edit_content_folder.php?_course_id='.$_course_id.'pid='.$cid);
\r
678 //// $shortcuts[] = array('title' => _AT('add_top_page'), 'url' => $_base_href . 'home/editor/edit_content.php?_course_id='.$_course_id, 'icon' => $_base_href . 'images/page_add.gif');
\r
679 // if ($contentManager->_menu_info[$cid]['content_parent_id']) {
\r
680 // $shortcuts[] = array('title' => _AT('add_sibling_page'), 'url' => $_base_href .
\r
681 // 'home/editor/edit_content.php?_course_id='.$_course_id.SEP.'pid='.$contentManager->_menu_info[$cid]['content_parent_id'], 'icon' => $_base_href . 'images/page_add_sibling.gif');
\r
684 // $shortcuts[] = array('title' => _AT('add_sub_page'), 'url' => $_base_href . 'home/editor/edit_content.php?_course_id='.$_course_id.SEP.'pid='.$cid);
\r
685 // $shortcuts[] = array('title' => _AT('delete_this_folder'), 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$cid, 'icon' => $_base_href . 'images/page_delete.gif');
\r
690 * replace source object with alternatives according to user's preferences
\r
692 * @param $cid: content id.
\r
693 * @param $content: the original content page ($content_row['text'], from content.php).
\r
694 * @param $info_only: when "true", return the array of info (has_text_alternative, has_audio_alternative, has_visual_alternative, has_sign_lang_alternative)
\r
695 * @param $only_on_secondary_type:
\r
696 * @return string $content: the content page with the appropriated resources.
\r
697 * @see $db from include/vitals.inc.php
\r
698 * @author Cindy Qi Li
\r
700 public static function applyAlternatives($cid, $content, $info_only = false, $only_on_secondary_type = 0){
\r
701 global $db, $_course_id;
\r
703 include_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php');
\r
706 $video_exts = array("mpg", "avi", "wmv", "mov", "swf", "mp3", "wav", "ogg", "mid", "mp4", "flv");
\r
707 $txt_exts = array("txt", "html", "htm");
\r
708 $image_exts = array("gif", "bmp", "png", "jpg", "jpeg", "png", "tif");
\r
709 $only_on_secondary_type = intval($only_on_secondary_type);
\r
711 // intialize the 4 returned values when $info_only is on
\r
714 $has_text_alternative = false;
\r
715 $has_audio_alternative = false;
\r
716 $has_visual_alternative = false;
\r
717 $has_sign_lang_alternative = false;
\r
720 if (!$info_only && !$only_on_secondary_type &&
\r
721 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_TEXT']==0) &&
\r
722 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_AUDIO']==0) &&
\r
723 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_VISUAL']==0))
\r
725 //No user's preferences related to content format are declared
\r
729 return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
\r
733 // get all relations between primary resources and their alternatives
\r
734 $sql = "SELECT c.content_path, pr.resource, prt.type_id primary_type, sr.secondary_resource, srt.type_id secondary_type
\r
735 FROM ".TABLE_PREFIX."primary_resources pr, ".
\r
736 TABLE_PREFIX."primary_resources_types prt,".
\r
737 TABLE_PREFIX."secondary_resources sr,".
\r
738 TABLE_PREFIX."secondary_resources_types srt,".
\r
739 TABLE_PREFIX."content c
\r
740 WHERE pr.content_id=".$cid."
\r
741 AND pr.primary_resource_id = prt.primary_resource_id
\r
742 AND pr.primary_resource_id = sr.primary_resource_id
\r
743 AND sr.language_code='".$_SESSION['lang']."'
\r
744 AND sr.secondary_resource_id = srt.secondary_resource_id
\r
745 AND pr.content_id = c.content_id";
\r
746 if ($only_on_secondary_type > 0) {
\r
747 $sql .= " AND srt.type_id=".$only_on_secondary_type;
\r
749 $sql .= " ORDER BY pr.primary_resource_id, prt.type_id";
\r
751 $rows = $dao->execute($sql);
\r
753 if (!is_array($rows)) {
\r
757 return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
\r
761 foreach ($rows as $row)
\r
763 if ($info_only || $only_on_secondary_type ||
\r
764 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_TEXT']==1 && $row['primary_type']==3 &&
\r
765 ($_SESSION['prefs']['PREF_ALT_TO_TEXT']=="audio" && $row['secondary_type']==1 ||
\r
766 $_SESSION['prefs']['PREF_ALT_TO_TEXT']=="visual" && $row['secondary_type']==4 ||
\r
767 $_SESSION['prefs']['PREF_ALT_TO_TEXT']=="sign_lang" && $row['secondary_type']==2)) ||
\r
769 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_AUDIO']==1 && $row['primary_type']==1 &&
\r
770 ($_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="visual" && $row['secondary_type']==4 ||
\r
771 $_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="text" && $row['secondary_type']==3 ||
\r
772 $_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="sign_lang" && $row['secondary_type']==2)) ||
\r
774 ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_VISUAL']==1 && $row['primary_type']==4 &&
\r
775 ($_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="audio" && $row['secondary_type']==1 ||
\r
776 $_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="text" && $row['secondary_type']==3 ||
\r
777 $_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="sign_lang" && $row['secondary_type']==2))
\r
780 $ext = substr($row['secondary_resource'], strrpos($row['secondary_resource'], '.')+1);
\r
782 // alternative is video
\r
783 if (in_array($ext, $video_exts))
\r
784 $target = '[media]'.$row['secondary_resource'].'[/media]';
\r
785 // a text primary to be replaced by a visual alternative
\r
786 else if (in_array($ext, $txt_exts))
\r
788 if ($row['content_path'] <> '')
\r
789 $file_location = $row['content_path'].'/'.$row['secondary_resource'];
\r
791 $file_location = $row['secondary_resource'];
\r
793 $file = TR_CONTENT_DIR.$_SESSION['course_id'] . '/'.$file_location;
\r
794 $target = '<br />'.file_get_contents($file);
\r
796 // check whether html file
\r
797 if (preg_match('/.*\<html.*\<\/html\>.*/s', $target))
\r
798 { // is a html file, use iframe to display
\r
799 // get real path to the text file
\r
800 if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) {
\r
801 $course_base_href = 'get.php/';
\r
803 $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
\r
806 $file = TR_BASE_HREF . $course_base_href.$file_location;
\r
808 $target = '<iframe width="100%" frameborder="0" class="autoHeight" scrolling="auto" src="'.$file.'"></iframe>';
\r
811 { // is a text file, insert/replace into content
\r
812 $target = nl2br($target);
\r
815 else if (in_array($ext, $image_exts))
\r
816 $target = '<img border="0" alt="'._AT('alternate_text').'" src="'.$row['secondary_resource'].'"/>';
\r
819 $target = '<p><a href="'.$row['secondary_resource'].'">'.$row['secondary_resource'].'</a></p>';
\r
821 // replace or append the target alternative to the source
\r
822 if (($row['primary_type']==3 && $_SESSION['prefs']['PREF_ALT_TO_TEXT_APPEND_OR_REPLACE'] == 'replace') ||
\r
823 ($row['primary_type']==1 && $_SESSION['prefs']['PREF_ALT_TO_AUDIO_APPEND_OR_REPLACE']=='replace') ||
\r
824 ($row['primary_type']==4 && $_SESSION['prefs']['PREF_ALT_TO_VISUAL_APPEND_OR_REPLACE']=='replace'))
\r
825 $pattern_replace_to = '${1}'.$target.'${3}';
\r
827 $pattern_replace_to = '${1}${2}'.$target.'${3}';
\r
829 // *** Alternative replace/append starts from here ***
\r
830 $img_processed = false; // The indicator to tell the source image is found (or not)
\r
831 // and processed (or not) in an <img> tag. If found and processed,
\r
832 // SKIP the found/process for <a> tag because the source is a image
\r
833 // and <a> is very likely the tag wrapping around <img>
\r
835 // append/replace target alternative to [media]source[/media]
\r
836 if (preg_match("/".preg_quote("[media").".*".preg_quote("]".$row['resource']."[/media]", "/")."/sU", $content))
\r
839 $content = preg_replace("/(.*)(".preg_quote("[media").".*".preg_quote("]".$row['resource']."[/media]", "/").")(.*)/sU",
\r
840 $pattern_replace_to, $content);
\r
842 if ($row['secondary_type'] == 1) $has_audio_alternative = true;
\r
843 if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
\r
844 if ($row['secondary_type'] == 3) $has_text_alternative = true;
\r
845 if ($row['secondary_type'] == 4) $has_visual_alternative = true;
\r
849 // append/replace target alternative to <img ... src="source" ...></a>
\r
850 if (preg_match("/\<img.*src=\"".preg_quote($row['resource'], "/")."\".*\/\>/sU", $content))
\r
852 $img_processed = true;
\r
854 $content = preg_replace("/(.*)(\<img.*src=\"".preg_quote($row['resource'], "/")."\".*\/\>)(.*)/sU",
\r
855 $pattern_replace_to, $content);
\r
857 if ($row['secondary_type'] == 1) $has_audio_alternative = true;
\r
858 if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
\r
859 if ($row['secondary_type'] == 3) $has_text_alternative = true;
\r
860 if ($row['secondary_type'] == 4) $has_visual_alternative = true;
\r
864 // append/replace target alternative to <a>...source...</a> or <a ...source...>...</a>
\r
865 // skip this "if" when the source object has been processed in aboved <img> tag
\r
866 if (!$img_processed && preg_match("/\<a.*".preg_quote($row['resource'], "/").".*\<\/a\>/sU", $content))
\r
869 $content = preg_replace("/(.*)(\<a.*".preg_quote($row['resource'], "/").".*\<\/a\>)(.*)/sU",
\r
870 $pattern_replace_to, $content);
\r
872 if ($row['secondary_type'] == 1) $has_audio_alternative = true;
\r
873 if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
\r
874 if ($row['secondary_type'] == 3) $has_text_alternative = true;
\r
875 if ($row['secondary_type'] == 4) $has_visual_alternative = true;
\r
879 // append/replace target alternative to <object ... source ...></object>
\r
880 if (preg_match("/\<object.*".preg_quote($row['resource'], "/").".*\<\/object\>/sU", $content))
\r
883 $content = preg_replace("/(.*)(\<object.*".preg_quote($row['resource'], "/").".*\<\/object\>)(.*)/sU",
\r
884 $pattern_replace_to, $content);
\r
886 if ($row['secondary_type'] == 1) $has_audio_alternative = true;
\r
887 if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
\r
888 if ($row['secondary_type'] == 3) $has_text_alternative = true;
\r
889 if ($row['secondary_type'] == 4) $has_visual_alternative = true;
\r
893 // append/replace target alternative to <embed ... source ...>
\r
894 if (preg_match("/\<embed.*".preg_quote($row['resource'], "/").".*\>/sU", $content))
\r
897 $content = preg_replace("/(.*)(\<embed.*".preg_quote($row['resource'], "/").".*\>)(.*)/sU",
\r
898 $pattern_replace_to, $content);
\r
900 if ($row['secondary_type'] == 1) $has_audio_alternative = true;
\r
901 if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
\r
902 if ($row['secondary_type'] == 3) $has_text_alternative = true;
\r
903 if ($row['secondary_type'] == 4) $has_visual_alternative = true;
\r
912 return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
\r
917 * This function save the last content_id accessed by current user on a course into db and set $_SESSION['s_cid']
\r
919 * @param: $content_id
\r
920 * @return: save $content_id, the last visited one of the current user, into db and session
\r
922 public static function saveLastCid($content_id)
\r
924 global $_course_id;
\r
926 if (!$content_id || !isset($_SESSION['user_id'])) return;
\r
928 include_once(TR_INCLUDE_PATH.'classes/DAO/UserCoursesDAO.class.php');
\r
930 $userCoursesDAO = new UserCoursesDAO();
\r
931 if ($userCoursesDAO->isExist($_SESSION['user_id'], $_course_id))
\r
933 $userCoursesDAO->UpdateLastCid($_SESSION['user_id'], $_course_id, $content_id);
\r
934 $_SESSION['s_cid'] = $content_id;
\r