PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/home/classes/ContentUtility.class.php

https://github.com/supungs/AContent
PHP | 1071 lines | 683 code | 153 blank | 235 comment | 206 complexity | 1b9b974df1a54e2888663376cb4ac735 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, MIT, AGPL-1.0
  1. <?php
  2. /************************************************************************/
  3. /* AContent */
  4. /************************************************************************/
  5. /* Copyright (c) 2013 */
  6. /* Inclusive Design Institute */
  7. /* */
  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. /************************************************************************/
  12. /**
  13. * Content Utility functions
  14. * @access public
  15. * @author Cindy Qi Li
  16. */
  17. if (!defined('TR_INCLUDE_PATH')) exit;
  18. class ContentUtility {
  19. /**
  20. * This function cuts out html body
  21. * @access public
  22. * @param $text html text
  23. * @author Cindy Qi Li
  24. */
  25. public static function getHtmlBody($text) {
  26. /* strip everything before <body> */
  27. $start_pos = strpos(strtolower($text), '<body');
  28. if ($start_pos !== false) {
  29. $start_pos += strlen('<body');
  30. $end_pos = strpos(strtolower($text), '>', $start_pos);
  31. $end_pos += strlen('>');
  32. $text = substr($text, $end_pos);
  33. }
  34. /* strip everything after </body> */
  35. $end_pos = strpos(strtolower($text), '</body>');
  36. if ($end_pos !== false) {
  37. $text = trim(substr($text, 0, $end_pos));
  38. }
  39. return $text;
  40. }
  41. public static function getHTMLContent($text) {
  42. //remove the content div if it exists
  43. if(strpos($text,'<div id="content">') !== false && strstr($text, '<div id="content">', true) == "") {
  44. //the div element with id=content is the first element so I remove it
  45. $text = substr($text, strlen('<div id="content">'));
  46. $text = trim(substr($text, 0, strlen($text)-strlen('</div>')));
  47. }
  48. return $text;
  49. }
  50. /**
  51. * This function cuts out requested tag information from html head
  52. * @access public
  53. * @param $text html text
  54. * @param $tags a string or an array of requested tags
  55. * @author Cindy Qi Li
  56. */
  57. public static function getHtmlHeadByTag($text, $tags)
  58. {
  59. $head = ContentUtility::getHtmlHead($text);
  60. $rtn_text = "";
  61. if (!is_array($tags) && strlen(trim($tags)) > 0)
  62. {
  63. $tags = array(trim($tags));
  64. }
  65. foreach ($tags as $tag)
  66. {
  67. $tag = strtolower($tag);
  68. /* strip everything before <{tag}> */
  69. $start_pos = stripos($head, '<'.$tag);
  70. $temp_head = $head;
  71. while ($start_pos !== false)
  72. {
  73. $temp_text = substr($temp_head, $start_pos);
  74. /* strip everything after </{tag}> or />*/
  75. $end_pos = stripos($temp_text, '</' . $tag . '>');
  76. if ($end_pos !== false)
  77. {
  78. $end_pos += strlen('</' . $tag . '>');
  79. // add an empty line after each tag information
  80. $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
  81. ';
  82. }
  83. else // match /> as ending tag if </tag> is not found
  84. {
  85. $end_pos = stripos($temp_text, '/>');
  86. if($end_pos === false && stripos($temp_text, $tag.'>')===false){
  87. //if /> is not found, then this is not a valid XHTML
  88. //text iff it's not tag>
  89. $end_pos = stripos($temp_text, '>');
  90. $end_pos += strlen('>');
  91. } else {
  92. $end_pos += strlen('/>');
  93. }
  94. // add an empty line after each tag information
  95. $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
  96. ';
  97. }
  98. // initialize vars for next round of matching
  99. $temp_head = substr($temp_text, $end_pos);
  100. $start_pos = stripos($temp_head, '<'.$tag);
  101. }
  102. }
  103. return $rtn_text;
  104. }
  105. /**
  106. * This function cuts out html head
  107. * @access private
  108. * @param $text html text
  109. * @author Cindy Qi Li
  110. */
  111. private static function getHtmlHead ($text) {
  112. /* strip everything before <head> */
  113. $start_pos = stripos($text, '<head');
  114. if ($start_pos !== false) {
  115. $start_pos += strlen('<head');
  116. $end_pos = stripos($text, '>', $start_pos);
  117. $end_pos += strlen('>');
  118. $text = substr($text, $end_pos);
  119. }
  120. /* strip everything after </head> */
  121. $end_pos = stripos($text, '</head');
  122. if ($end_pos !== false) {
  123. $text = trim(substr($text, 0, $end_pos));
  124. }
  125. return $text;
  126. }
  127. private static function embedFLV($text) {
  128. global $content_base_href;
  129. $media_replace = array();
  130. $media_matches = array();
  131. $flowplayerholder_class = "atutor.flowplayerholder"; // style class used to play flowplayer medias
  132. $flowplayerholder_def = '$f("*.'.$flowplayerholder_class.'"'; // javascript definition for atutor.flowplayerholder
  133. // .flv
  134. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+)\.flv\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  135. if (isset($_SESSION['flash']) && $_SESSION['flash'] == "yes") {
  136. $media_replace[] = "<div>\n".
  137. " <a class=\"".$flowplayerholder_class."\" style=\"display:block;width:##WIDTH##px;height:##HEIGHT##px;\" href=\"##MEDIA1##.flv\"></a>\n".
  138. "</div>\n";
  139. } else {
  140. $media_replace[] = "<div>\n".
  141. " <a href=\"##MEDIA1##.flv\">##MEDIA1##.flv</a>\n".
  142. "</div>\n";
  143. }
  144. // .mp4
  145. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+)\.mp4\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  146. if (isset($_SESSION['flash']) && $_SESSION['flash'] == "yes") {
  147. $media_replace[] = "<div>\n".
  148. " <a class=\"".$flowplayerholder_class."\" style=\"display:block;width:##WIDTH##px;height:##HEIGHT##px;\" href=\"##MEDIA1##.mp4\"></a>\n".
  149. "</div>\n";
  150. } else {
  151. $media_replace[] = "<div>\n".
  152. " <a href=\"##MEDIA1##.mp4\">##MEDIA1##.mp4</a>\n".
  153. "</div>\n";
  154. }
  155. // Executing the replace
  156. for ($i=0;$i<count($media_replace);$i++){
  157. foreach($media_matches[$i] as $media)
  158. {
  159. //find width and height for each matched media
  160. if (preg_match("/\[media\|([0-9]*)\|([0-9]*)\]*/", $media[0], $matches))
  161. {
  162. $width = $matches[1];
  163. $height = $matches[2];
  164. }
  165. else
  166. {
  167. $width = 425;
  168. $height = 350;
  169. }
  170. //replace media tags with embedded media for each media tag
  171. $media_input = $media_replace[$i];
  172. $media_input = str_replace("##WIDTH##","$width",$media_input);
  173. $media_input = str_replace("##HEIGHT##","$height",$media_input);
  174. $media_input = str_replace("##MEDIA1##","$media[1]",$media_input);
  175. $media_input = str_replace("##MEDIA2##","$media[2]",$media_input);
  176. $text = str_replace($media[0],$media_input,$text);
  177. }
  178. }
  179. // Include the javascript only if:
  180. // 1. $flowplayerholder_class is used but not defined
  181. // 2. exclude from export common cartridge or content package
  182. if (strpos($text, $flowplayerholder_class)
  183. && !strpos($text, $flowplayerholder_def)
  184. && !strpos($_SERVER['PHP_SELF'], "ims_export.php"))
  185. {
  186. $text .= '<script type="text/javascript">
  187. '.$flowplayerholder_def.', "'.TR_BASE_HREF.'include/jscripts/flowplayer/flowplayer-3.2.4.swf", {
  188. clip: {
  189. autoPlay: false,
  190. baseUrl: \''.TR_BASE_HREF.'get.php/'.$content_base_href.'\'},
  191. plugins: {
  192. controls: {
  193. buttons:true,
  194. play: true,
  195. scrubber: true,
  196. autoHide:false
  197. }
  198. }
  199. });
  200. </script>'."\n";
  201. }
  202. return $text;
  203. }
  204. /*
  205. * This function converts the youtube playable url used in <object> tag (for instance: http://www.youtube.com/v/a0ryB0m0MiM)
  206. * to youtube url that is used to browse (for instance: http://www.youtube.com/watch?v=a0ryB0m0MiM)
  207. * @param: youtube playable URL. For instance, http://www.youtube.com/v/a0ryB0m0MiM
  208. * @return: if the param is a youtube playable url, return the according youtube URL used to browse.
  209. * For instance: http://www.youtube.com/watch?v=a0ryB0m0MiM
  210. * Otherwise, return the original send-in parameter.
  211. */
  212. public static function convertYoutubePlayURLToWatchURL($youtube_playURL) {
  213. return preg_replace("/(http:\/\/[a-z0-9\.]*)?youtube.com\/v\/(.*)/",
  214. "\\1youtube.com/watch?v=\\2", $youtube_playURL);
  215. }
  216. /*
  217. * This function converts the youtube url that is used to browse (for instance: http://www.youtube.com/watch?v=a0ryB0m0MiM)
  218. * to youtube playable url used in <object> tag (for instance: http://www.youtube.com/v/a0ryB0m0MiM)
  219. * @param: the youtube URL used to browse.
  220. * For instance: http://www.youtube.com/watch?v=a0ryB0m0MiM
  221. * @return: if the param is a youtube url used to browse, return the according youtube playable URL.
  222. * For instance, http://www.youtube.com/v/a0ryB0m0MiM
  223. * Otherwise, return the original send-in parameter.
  224. */
  225. public function convertYoutubeWatchURLToPlayURL($youtube_watchURL) {
  226. return preg_replace("/(http:\/\/[a-z0-9\.]*)?youtube.com\/watch\?v=(.*)/",
  227. "\\1youtube.com/v/\\2", $youtube_watchURL);
  228. }
  229. public static function embedMedia($text) {
  230. if (preg_match("/\[media(\|[0-9]+\|[0-9]+)?\]*/", $text)==0){
  231. return $text;
  232. }
  233. // remove the spaces in [media] tag, otherwise, the next line converts URL inside [media] into <a> tag
  234. $text = preg_replace("/(\[media\])([\s]*)(.*)(\[\/media\])/", '$1$3$4', $text);
  235. $text = preg_replace("/(\[media\])(.*)([\s]*)(\[\/media\])/U", '$1$2$4', $text);
  236. $media_matches = array();
  237. $media_replace = array();
  238. // First, we search though the text for all different kinds of media defined by media tags and store the results in $media_matches.
  239. // Then the different replacements for the different media tags are stored in $media_replace.
  240. // 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.
  241. // youtube videos
  242. preg_match_all("#\[media[0-9a-z\|]*\]http://([a-z0-9\.]*)?youtube.com/watch\?v=(.*)\[/media\]#iU",$text,$media_matches[],PREG_SET_ORDER);
  243. $media_replace[] = '<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>';
  244. // .mpg
  245. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mpg\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  246. $media_replace[] = "<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>";
  247. // .avi
  248. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).avi\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  249. $media_replace[] = "<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>";
  250. // .wmv
  251. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).wmv\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  252. $media_replace[] = "<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>";
  253. // .mov
  254. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mov\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  255. $media_replace[] = "<object classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\" codebase=\"http://www.apple.com/qtactivex/qtplugin.cab\" width=\"##WIDTH##\" height=\"##HEIGHT##\">\n".
  256. " <param name=\"src\" value=\"##MEDIA1##.mov\">\n".
  257. " <param name=\"controller\" value=\"true\">\n".
  258. " <param name=\"autoplay\" value=\"false\">\n".
  259. " <!--[if gte IE 7] > <!-->\n".
  260. " <object type=\"video/quicktime\" data=\"##MEDIA1##.mov\" width=\"##WIDTH##\" height=\"##HEIGHT##\">\n".
  261. " <param name=\"controller\" value=\"true\">\n".
  262. " <param name=\"autoplay\" value=\"false\">\n".
  263. " <a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a>\n".
  264. " </object>\n".
  265. " <!--<![endif]-->\n".
  266. " <!--[if lt IE 7]>\n".
  267. " <a href=\"##MEDIA1##.mov\">##MEDIA1##.mov</a>\n".
  268. " <![endif]-->\n".
  269. "</object>";
  270. // .swf
  271. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).swf\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  272. $media_replace[] = "<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>";
  273. // .mp3
  274. preg_match_all("#\[media[0-9a-z\|]*\]([.\w\d]+[^\s\"]+).mp3\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  275. $media_replace[] = "<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>";
  276. // .wav
  277. preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).wav\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  278. $media_replace[] ="<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>";
  279. // .ogg
  280. preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).ogg\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  281. $media_replace[] ="<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>";
  282. // .ogm
  283. preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).ogm\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  284. $media_replace[] ="<object type=\"application/ogm\" data=\"##MEDIA1##.ogm\" width=\"##WIDTH##\" height=\"##HEIGHT##\"><param name=\"src\" value=\"##MEDIA1##.ogm\"><a href=\"##MEDIA1##.ogg\">##MEDIA1##.ogm</a></object>";
  285. // .mid
  286. preg_match_all("#\[media[0-9a-z\|]*\](.+[^\s\"]+).mid\[/media\]#i",$text,$media_matches[],PREG_SET_ORDER);
  287. $media_replace[] ="<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>";
  288. $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);
  289. // Executing the replace
  290. for ($i=0;$i<count($media_replace);$i++){
  291. foreach($media_matches[$i] as $media)
  292. {
  293. //find width and height for each matched media
  294. if (preg_match("/\[media\|([0-9]*)\|([0-9]*)\]*/", $media[0], $matches))
  295. {
  296. $width = $matches[1];
  297. $height = $matches[2];
  298. }
  299. else
  300. {
  301. $width = 425;
  302. $height = 350;
  303. }
  304. //replace media tags with embedded media for each media tag
  305. $media_input = $media_replace[$i];
  306. $media_input = str_replace("##WIDTH##","$width",$media_input);
  307. $media_input = str_replace("##HEIGHT##","$height",$media_input);
  308. $media_input = str_replace("##MEDIA1##","$media[1]",$media_input);
  309. $media_input = str_replace("##MEDIA2##","$media[2]",$media_input);
  310. $text = str_replace($media[0],$media_input,$text);
  311. }
  312. }
  313. return $text;
  314. }
  315. public static function makeClickable($text) {
  316. $text = ContentUtility::embedMedia($text);
  317. // convert plain text URL to clickable URL.
  318. // Limited conversion: It doesn't cover the case when the stuff in front of the URL is not a word. For example:
  319. // <p>http://google.ca</p>
  320. // "http://google.ca"
  321. $text = preg_replace('/(^|[\n ])([\w]*?)((?<!(\[media\]))http(s)?:\/\/[\w]+[^ \,\"\n\r\t\)<]*)/is',
  322. '$1$2<a href="$3">$3</a>', $text);
  323. // convert email address to clickable URL that pops up "send email" interface with the address filled in
  324. $text = preg_replace('/(?|<a href="mailto[\s]*:[\s]*([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'\@'
  325. .'[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'(\.[a-zA-Z]{1,6})+)">(.*)<\/a>'
  326. .'|((((([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'\@'
  327. .'[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*'.'(\.[a-zA-Z]{1,6})+))))))/i',
  328. "<a href=\"mailto:\\1\">\\5</a>",
  329. $text);
  330. // flv conversion needs to come after url conversion (2 lines above) otherwise the url to flowplayer swf file
  331. // in the script for a.flowplayerholder is converted
  332. $text = ContentUtility::embedFLV($text);
  333. return $text;
  334. }
  335. public static function myCodes($text, $html = false) {
  336. global $_base_path;
  337. global $HTTP_USER_AGENT;
  338. if (substr($HTTP_USER_AGENT,0,11) == 'Mozilla/4.7') {
  339. $text = str_replace('[quote]','</p><p class="block">',$text);
  340. $text = str_replace('[/quote]','</p><p>',$text);
  341. $text = str_replace('[reply]','</p><p class="block">',$text);
  342. $text = str_replace('[/reply]','</p><p>',$text);
  343. } else {
  344. $text = str_replace('[quote]','<blockquote>',$text);
  345. $text = str_replace('[/quote]','</blockquote><p>',$text);
  346. $text = str_replace('[reply]','</p><blockquote class="block"><p>',$text);
  347. $text = str_replace('[/reply]','</p></blockquote><p>',$text);
  348. }
  349. $text = str_replace('[b]','<strong>',$text);
  350. $text = str_replace('[/b]','</strong>',$text);
  351. $text = str_replace('[i]','<em>',$text);
  352. $text = str_replace('[/i]','</em>',$text);
  353. $text = str_replace('[u]','<u>',$text);
  354. $text = str_replace('[/u]','</u>',$text);
  355. $text = str_replace('[center]','<center>',$text);
  356. $text = str_replace('[/center]','</center><p>',$text);
  357. /* colours */
  358. $text = str_replace('[blue]','<span style="color: blue;">',$text);
  359. $text = str_replace('[/blue]','</span>',$text);
  360. $text = str_replace('[orange]','<span style="color: orange;">',$text);
  361. $text = str_replace('[/orange]','</span>',$text);
  362. $text = str_replace('[red]','<span style="color: red;">',$text);
  363. $text = str_replace('[/red]','</span>',$text);
  364. $text = str_replace('[purple]','<span style="color: purple;">',$text);
  365. $text = str_replace('[/purple]','</span>',$text);
  366. $text = str_replace('[green]','<span style="color: green;">',$text);
  367. $text = str_replace('[/green]','</span>',$text);
  368. $text = str_replace('[gray]','<span style="color: gray;">',$text);
  369. $text = str_replace('[/gray]','</span>',$text);
  370. $text = str_replace('[op]','<span class="bigspacer"></span> <a href="',$text);
  371. $text = str_replace('[/op]','">'._AT('view_entire_post').'</a>',$text);
  372. $text = str_replace('[head1]','<h2>',$text);
  373. $text = str_replace('[/head1]','</h2>',$text);
  374. $text = str_replace('[head2]','<h3>',$text);
  375. $text = str_replace('[/head2]','</h3>',$text);
  376. $text = str_replace('[cid]',$_base_path.'content.php?_cid='.$_SESSION['s_cid'],$text);
  377. global $sequence_links, $_course_id, $_content_id;
  378. if ($_course_id > 0 && !isset($sequence_links) && $_content_id > 0) {
  379. global $contentManager;
  380. $sequence_links = $contentManager->generateSequenceCrumbs($_content_id);
  381. }
  382. if (isset($sequence_links['previous']) && $sequence_links['previous']['url']) {
  383. $text = str_replace('[pid]', $sequence_links['previous']['url'], $text);
  384. }
  385. if (isset($sequence_links['next']) && $sequence_links['next']['url']) {
  386. $text = str_replace('[nid]', $sequence_links['next']['url'], $text);
  387. }
  388. if (isset($sequence_links['resume']) && $sequence_links['resume']['url']) {
  389. $text = str_replace('[nid]', $sequence_links['resume']['url'], $text);
  390. }
  391. if (isset($sequence_links['first']) && $sequence_links['first']['url']) {
  392. $text = str_replace('[fid]', $sequence_links['first']['url'], $text);
  393. }
  394. /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
  395. $html = !$html ? 0 : 1;
  396. // little hack added by greg to add syntax highlighting without using <?php \?\>
  397. $text = str_replace("[code]","[code]<?php",$text);
  398. $text = str_replace("[/code]","?>[/code]",$text);
  399. $text = preg_replace("/\[code\]\s*(.*)\s*\[\\/code\]/Usei", "ContentUtility::highlightCode(ContentUtility::fixQuotes('\\1'), $html)", $text);
  400. // now remove the <?php added above and leave the syntax colour behind.
  401. $text = str_replace("&lt;?php", "", $text);
  402. $text = str_replace("?&gt;", "", $text);
  403. return $text;
  404. }
  405. /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
  406. private static function highlightCode($code, $html) {
  407. // XHTMLize PHP highlight_string output until it gets fixed in PHP
  408. static $search = array(
  409. '<br>',
  410. '<font',
  411. '</font>',
  412. 'color="');
  413. static $replace = array(
  414. '<br />',
  415. '<span',
  416. '</span>',
  417. 'style="color:');
  418. if (!$html) {
  419. $code = str_replace('&lt;', '<', $code);
  420. $code = str_replace("\r", '', $code);
  421. }
  422. return str_replace($search, $replace, highlight_string($code, true));
  423. }
  424. /* contributed by Thomas M. Duffey <tduffey at homeboyz.com> */
  425. private static function fixQuotes($text){
  426. return str_replace('\\"', '"', $text);
  427. }
  428. public static function imageReplace($text) {
  429. /* image urls do not require http:// */
  430. // $text = eregi_replace("\[image(\|)?([[:alnum:][:space:]]*)\]" .
  431. // "[:space:]*" .
  432. // "([[:alnum:]#?/&=:\"'_.-]+)" .
  433. // "[:space:]*" .
  434. // "((\[/image\])|(.*\[/image\]))",
  435. // "<img src=\"\\3\" alt=\"\\2\" />",
  436. // $text);
  437. $text = preg_replace("/\[image(\|)?([a-zA-Z0-9\s]*)\]".
  438. "[\s]*".
  439. "([a-zA-Z0-9\#\?\/\&\=\:\\\"\'\_\.\-]+)[\s]*".
  440. "((\[\/image\])|(.*\[\/image\]))/i",
  441. "<img src=\"\\3\" alt=\"\\2\" />",
  442. $text);
  443. return $text;
  444. }
  445. private static function formatFinalOutput($text, $nl2br = true) {
  446. global $_base_path;
  447. $text = str_replace('CONTENT_DIR/', '', $text);
  448. if ($nl2br) {
  449. return nl2br(ContentUtility::imageReplace(ContentUtility::makeClickable(ContentUtility::myCodes(' '.$text, false))));
  450. }
  451. return ContentUtility::imageReplace(ContentUtility::makeClickable(ContentUtility::myCodes(' '.$text, true)));
  452. }
  453. /**
  454. * This function converts the input string into AContent html content string
  455. * @access public
  456. * @param $input: input string
  457. * $html: whether the input is in html
  458. * @return converted AContent html content string
  459. * @author Cindy Qi Li
  460. */
  461. public static function formatContent($input, $html = 0) {
  462. global $_base_path, $_config;
  463. if (!$html) {
  464. $input = str_replace('<', '&lt;', $input);
  465. $input = str_replace('&lt;?php', '<?php', $input); // for bug #2087
  466. } elseif ($html==2) {
  467. $output = '<iframe width="100%" frameborder="0" id="content_frame" marginheight="0" marginwidth="0" src="'.$input.'"></iframe>';
  468. $output .= '<script type="text/javascript">
  469. function resizeIframe() {
  470. var height = document.documentElement.clientHeight;
  471. // not sure how to get this dynamically
  472. height -= 20; /* whatever you set your body bottom margin/padding to be */
  473. document.getElementById(\'content_frame\').style.height = height +"px";
  474. };
  475. document.getElementById(\'content_frame\').onload = resizeIframe;
  476. window.onresize = resizeIframe;
  477. </script>';
  478. return $output;
  479. }
  480. /* Commented by Cindy Qi Li on Jan 12, 2010
  481. * AContent does not support glossary
  482. // do the glossary search and replace:
  483. if (is_array($glossary)) {
  484. foreach ($glossary as $k => $v) {
  485. $k = urldecode($k);
  486. $v = str_replace("\n", '<br />', $v);
  487. $v = str_replace("\r", '', $v);
  488. // escape special characters
  489. $k = preg_quote($k);
  490. $k = str_replace('&lt;', '<', $k);
  491. $k = str_replace('/', '\/', $k);
  492. $original_term = $k;
  493. $term = $original_term;
  494. $term = '(\s*'.$term.'\s*)';
  495. $term = str_replace(' ','((<br \/>)*\s*)', $term);
  496. $def = htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
  497. if ($simple) {
  498. $input = preg_replace
  499. ("/(\[\?\])$term(\[\/\?\])/i",
  500. '<a href="'.$simple.'glossary.html#'.urlencode($original_term).'" target="body" class="at-term">\\2</a>',
  501. $input);
  502. } else {
  503. $input = preg_replace
  504. ("/(\[\?\])$term(\[\/\?\])/i",
  505. '\\2<sup><a class="tooltip" href="'.$_base_path.'mods/_core/glossary/index.php?g_cid='.$_SESSION['s_cid'].htmlentities(SEP).'w='.urlencode($original_term).'#term" title="'.addslashes($original_term).': '.$def.'">?</a></sup>',$input);
  506. }
  507. }
  508. } else if (!$user_glossary) {
  509. $input = str_replace(array('[?]','[/?]'), '', $input);
  510. }
  511. */
  512. $input = str_replace('CONTENT_DIR', '', $input);
  513. if (isset($_config['latex_server']) && $_config['latex_server']) {
  514. // see: http://www.forkosh.com/mimetex.html
  515. $input = preg_replace('/\[tex\](.*?)\[\/tex\]/sie', "'<img src=\"'.\$_config['latex_server'].rawurlencode('$1').'\" align=\"middle\">'", $input);
  516. }
  517. if ($html) {
  518. $x = ContentUtility::formatFinalOutput($input, false);
  519. return $x;
  520. }
  521. // the following has been taken out for this:
  522. // http://atutor.ca/atutor/mantis/view.php?id=4593
  523. // @date Oct 18, 2010
  524. // $output = ContentUtility::formatFinalOutput($input);
  525. $output = $input;
  526. $output = '<p>'.$input.'</p>';
  527. return $output;
  528. }
  529. /**
  530. * This function returns html string of "table of content"
  531. * @access: public
  532. * @param: $content: a string
  533. * @return: a html string of "table of content"
  534. */
  535. public static function getContentTable($content)
  536. {
  537. preg_match_all("/<(h[\d]+)[^>]*>(.*)<\/(\s*)\\1(\s*)>/i", $content, $found_headers, PREG_SET_ORDER);
  538. if (count($found_headers) == 0) return array("", $content);
  539. else
  540. {
  541. $num_of_headers = 0;
  542. for ($i = 0; $i < count($found_headers); $i++)
  543. {
  544. $div_id = "_header_" . $num_of_headers++;
  545. if ($i == 0)
  546. {
  547. $content_table = "<div id=\"toc\">\n<fieldset id=\"toc\"><legend>". _AT("table_of_contents")."</legend>\n";
  548. }
  549. $content = str_replace($found_headers[$i][0], '<div id="'.$div_id.'">'.$found_headers[$i][0].'</div>', $content);
  550. $content_table .= '<a href="'.$_SERVER["REQUEST_URI"].'#'.$div_id.'" class="'.$found_headers[$i][1].'">'. $found_headers[$i][2]."</a>\n";
  551. if ($i == count($found_headers) - 1)
  552. {
  553. $content_table .= "</fieldset></div><br />";
  554. }
  555. }
  556. return array($content_table, $content);
  557. }
  558. }
  559. /**
  560. * This function returns an array of content tools' shortcuts
  561. * @access: public
  562. * @param: $content_row: an array of the current content information
  563. * @return: an array of all the tool short cuts that apply to the current content or content folder
  564. */
  565. public static function getToolShortcuts($content_row)
  566. {
  567. global $_current_user, $_base_href, $contentManager, $_course_id;
  568. if (((!$content_row['content_parent_id'] && ($_SESSION['packaging'] == 'top'))
  569. || ($_SESSION['packaging'] == 'all'))
  570. || (isset($_current_user) && ($_current_user->isAuthor($_course_id)|| $_current_user->isAdmin()))) {
  571. $tool_shortcuts[] = array(
  572. 'title' => _AT('export_content_in_cp'),
  573. 'url' => $_base_href . 'home/ims/ims_export.php?_cid='.$content_row['content_id'],
  574. 'icon' => $_base_href . 'themes/'.$_SESSION['prefs']['PREF_THEME'].'/images/export.png');
  575. $tool_shortcuts[] = array(
  576. 'title' => _AT('export_content_in_cc'),
  577. 'url' => $_base_href . 'home/imscc/ims_export.php?_cid='.$content_row['content_id'].SEP.'to_a4a=1',
  578. 'icon' => $_base_href . 'themes/'.$_SESSION['prefs']['PREF_THEME'].'/images/export_cc.png');
  579. }
  580. if (isset($_current_user) && ($_current_user->isAuthor($_course_id) || $_current_user->isAdmin())) {
  581. if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
  582. $tool_shortcuts[] = array(
  583. 'title' => _AT('edit_this_page'),
  584. 'url' => $_base_href . 'home/editor/edit_content.php?_cid='.$content_row['content_id'],
  585. 'icon' => $_base_href . 'images/medit.gif');
  586. }
  587. global $_config;
  588. if($_config['enable_template_structure'] == '1'){
  589. $tool_shortcuts[] = array(
  590. 'title' => _AT('add_top_structure'),
  591. 'url' => $_base_href .
  592. 'home/editor/edit_content_struct.php?_course_id='.$_course_id,
  593. 'icon' => $_base_href . 'images/addstruct.gif');
  594. }
  595. $tool_shortcuts[] = array(
  596. 'title' => _AT('add_sibling_folder'),
  597. 'url' => $_base_href .
  598. 'home/editor/edit_content_folder.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'].SEP.'_course_id='.$_course_id,
  599. 'icon' => $_base_href . 'images/add_sibling_folder.gif');
  600. if ($content_row['content_type'] == CONTENT_TYPE_FOLDER || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
  601. $tool_shortcuts[] = array(
  602. 'title' => _AT('add_sub_folder'),
  603. 'url' => $_base_href .
  604. 'home/editor/edit_content_folder.php?_course_id='.$_course_id.SEP.'pid='.$content_row['content_id'],
  605. 'icon' => $_base_href . 'images/add_sub_folder.gif');
  606. }
  607. $tool_shortcuts[] = array(
  608. 'title' => _AT('add_sibling_page'),
  609. 'url' => $_base_href .
  610. 'home/editor/edit_content.php?pid='.$contentManager->_menu_info[$content_row['content_id']]['content_parent_id'].SEP.'_course_id='.$_course_id,
  611. 'icon' => $_base_href . 'images/add_sibling_page.gif');
  612. if ($content_row['content_type'] == CONTENT_TYPE_CONTENT || $content_row['content_type'] == CONTENT_TYPE_WEBLINK) {
  613. $tool_shortcuts[] = array(
  614. 'title' => _AT('delete_this_page'),
  615. 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$content_row['content_id'],
  616. 'icon' => $_base_href . 'images/page_delete.gif');
  617. }
  618. else if ($content_row['content_type'] == CONTENT_TYPE_FOLDER) {
  619. $tool_shortcuts[] = array(
  620. 'title' => _AT('add_sub_page'),
  621. 'url' => $_base_href . 'home/editor/edit_content.php?_course_id='.$_course_id.SEP.'pid='.$content_row['content_id'],
  622. 'icon' => $_base_href . 'images/add_sub_page.gif');
  623. $tool_shortcuts[] = array(
  624. 'title' => _AT('delete_this_folder'),
  625. 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$content_row['content_id'],
  626. 'icon' => $_base_href . 'images/page_delete.gif');
  627. }
  628. }
  629. return $tool_shortcuts;
  630. // if (isset($_current_user) && $_current_user->isAuthor($_course_id)) {
  631. // $shortcuts[] = array('title' => _AT('add_sub_folder'), 'url' => $_base_href . 'home/editor/edit_content_folder.php?_course_id='.$_course_id.'pid='.$cid);
  632. //
  633. //// $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');
  634. // if ($contentManager->_menu_info[$cid]['content_parent_id']) {
  635. // $shortcuts[] = array('title' => _AT('add_sibling_page'), 'url' => $_base_href .
  636. // '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');
  637. // }
  638. //
  639. // $shortcuts[] = array('title' => _AT('add_sub_page'), 'url' => $_base_href . 'home/editor/edit_content.php?_course_id='.$_course_id.SEP.'pid='.$cid);
  640. // $shortcuts[] = array('title' => _AT('delete_this_folder'), 'url' => $_base_href . 'home/editor/delete_content.php?_cid='.$cid, 'icon' => $_base_href . 'images/page_delete.gif');
  641. // }
  642. }
  643. /**
  644. * replace source object with alternatives according to user's preferences
  645. * @access public
  646. * @param $cid: content id.
  647. * @param $content: the original content page ($content_row['text'], from content.php).
  648. * @param $info_only: when "true", return the array of info (has_text_alternative, has_audio_alternative, has_visual_alternative, has_sign_lang_alternative)
  649. * @param $only_on_secondary_type:
  650. * @return string $content: the content page with the appropriated resources.
  651. * @see $db from include/vitals.inc.php
  652. * @author Cindy Qi Li
  653. */
  654. public static function applyAlternatives($cid, $content, $info_only = false, $only_on_secondary_type = 0){
  655. global $db, $_course_id;
  656. include_once(TR_INCLUDE_PATH.'classes/DAO/DAO.class.php');
  657. $dao = new DAO();
  658. $video_exts = array("mpg", "avi", "wmv", "mov", "swf", "mp4", "flv");
  659. $audio_exts = array("mp3", "wav", "ogg", "mid");
  660. $audio_width = 425;
  661. $audio_height = 27;
  662. $txt_exts = array("txt", "html", "htm");
  663. $image_exts = array("gif", "bmp", "png", "jpg", "jpeg", "png", "tif");
  664. $only_on_secondary_type = intval($only_on_secondary_type);
  665. // intialize the 4 returned values when $info_only is on
  666. if ($info_only)
  667. {
  668. $has_text_alternative = false;
  669. $has_audio_alternative = false;
  670. $has_visual_alternative = false;
  671. $has_sign_lang_alternative = false;
  672. }
  673. if (!$info_only && !$only_on_secondary_type &&
  674. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_TEXT']==0) &&
  675. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_AUDIO']==0) &&
  676. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_VISUAL']==0))
  677. {
  678. //No user's preferences related to content format are declared
  679. if (!$info_only) {
  680. return $content;
  681. } else {
  682. return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
  683. }
  684. }
  685. // get all relations between primary resources and their alternatives
  686. $sql = "SELECT DISTINCT c.content_path, pr.resource, prt.type_id primary_type,
  687. sr.secondary_resource, srt.type_id secondary_type
  688. FROM ".TABLE_PREFIX."primary_resources pr, ".
  689. TABLE_PREFIX."primary_resources_types prt,".
  690. TABLE_PREFIX."secondary_resources sr,".
  691. TABLE_PREFIX."secondary_resources_types srt,".
  692. TABLE_PREFIX."content c
  693. WHERE pr.content_id=".$cid."
  694. AND pr.primary_resource_id = prt.primary_resource_id
  695. AND pr.primary_resource_id = sr.primary_resource_id
  696. AND sr.language_code='".$_SESSION['lang']."'
  697. AND sr.secondary_resource_id = srt.secondary_resource_id
  698. AND pr.content_id = c.content_id";
  699. if ($only_on_secondary_type > 0) {
  700. $sql .= " AND srt.type_id=".$only_on_secondary_type;
  701. }
  702. $sql .= " ORDER BY pr.primary_resource_id, prt.type_id";
  703. $rows = $dao->execute($sql);
  704. if (!is_array($rows)) {
  705. if (!$info_only) {
  706. return $content;
  707. } else {
  708. return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
  709. }
  710. }
  711. $primary_resource_names = array();
  712. foreach ($rows as $row) {
  713. // if the primary resource is defined with multiple resource type,
  714. // the primary resource would be replaced/appended multiple times.
  715. // This is what we want at applying alternatives by default, but
  716. // not when only one secondary type is chosen to apply.
  717. // This fix is to remove the duplicates on the same primary resource.
  718. // A dilemma of this fix is, for example, if the primary resource type
  719. // is "text" and "visual", but
  720. // $_SESSION['prefs']['PREF_ALT_TO_TEXT_APPEND_OR_REPLACE'] == 'replace'
  721. // $_SESSION['prefs']['PREF_ALT_TO_VISUAL_APPEND_OR_REPLACE'] == 'append'
  722. // so, should replace happen or append happen? With this fix, whichever
  723. // the first in the sql return gets preserved in the array and processed.
  724. // The further improvement is requried to keep rows based on the selected
  725. // secondary type (http://www.atutor.ca/atutor/mantis/view.php?id=4598).
  726. if ($only_on_secondary_type > 0) {
  727. if (in_array($row['resource'], $primary_resource_names)) {
  728. continue;
  729. } else {
  730. $primary_resource_names[] = $row['resource'];
  731. }
  732. }
  733. $alternative_rows[] = $row;
  734. $youtube_playURL = ContentUtility::convertYoutubeWatchURLToPlayURL($row['resource']);
  735. if ($row['resource'] <> $youtube_playURL) {
  736. $row['resource'] = $youtube_playURL;
  737. $alternative_rows[] = $row;
  738. }
  739. }
  740. foreach ($alternative_rows as $row)
  741. {
  742. if ($info_only || $only_on_secondary_type ||
  743. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_TEXT']==1 && $row['primary_type']==3 &&
  744. ($_SESSION['prefs']['PREF_ALT_TO_TEXT']=="audio" && $row['secondary_type']==1 ||
  745. $_SESSION['prefs']['PREF_ALT_TO_TEXT']=="visual" && $row['secondary_type']==4 ||
  746. $_SESSION['prefs']['PREF_ALT_TO_TEXT']=="sign_lang" && $row['secondary_type']==2)) ||
  747. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_AUDIO']==1 && $row['primary_type']==1 &&
  748. ($_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="visual" && $row['secondary_type']==4 ||
  749. $_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="text" && $row['secondary_type']==3 ||
  750. $_SESSION['prefs']['PREF_ALT_TO_AUDIO']=="sign_lang" && $row['secondary_type']==2)) ||
  751. ($_SESSION['prefs']['PREF_USE_ALTERNATIVE_TO_VISUAL']==1 && $row['primary_type']==4 &&
  752. ($_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="audio" && $row['secondary_type']==1 ||
  753. $_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="text" && $row['secondary_type']==3 ||
  754. $_SESSION['prefs']['PREF_ALT_TO_VISUAL']=="sign_lang" && $row['secondary_type']==2))
  755. )
  756. {
  757. $ext = substr($row['secondary_resource'], strrpos($row['secondary_resource'], '.')+1);
  758. // alternative is video
  759. if (in_array($ext, $video_exts)|| in_array($ext, $audio_exts) ||
  760. preg_match("/http:\/\/.*youtube.com\/watch.*/", $row['secondary_resource'])) {
  761. if (in_array($ext, $audio_exts)) {
  762. // display audio medias in a smaller width/height (425 * 27)
  763. // A hack for now to handle audio media player size
  764. $target = '[media|'.$audio_width.'|'.$audio_height.']'.$row['secondary_resource'].'[/media]';
  765. } else {
  766. // use default media size for video medias
  767. $target = '[media]'.$row['secondary_resource'].'[/media]';
  768. }
  769. }
  770. // a text primary to be replaced by a visual alternative
  771. else if (in_array($ext, $txt_exts))
  772. {
  773. if ($row['content_path'] <> '')
  774. $file_location = $row['content_path'].'/'.$row['secondary_resource'];
  775. else
  776. $file_location = $row['secondary_resource'];
  777. $file = TR_CONTENT_DIR.$_SESSION['course_id'] . '/'.$file_location;
  778. $target = '<br />'.file_get_contents($file);
  779. // check whether html file
  780. if (preg_match('/.*\<html.*\<\/html\>.*/s', $target))
  781. { // is a html file, use iframe to display
  782. // get real path to the text file
  783. if (defined('TR_FORCE_GET_FILE') && TR_FORCE_GET_FILE) {
  784. $course_base_href = 'get.php/';
  785. } else {
  786. $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
  787. }
  788. $file = TR_BASE_HREF . $course_base_href.$file_location;
  789. $target = '<iframe width="100%" frameborder="0" class="autoHeight" scrolling="auto" src="'.$file.'"></iframe>';
  790. }
  791. else
  792. { // is a text file, insert/replace into content
  793. $target = nl2br($target);
  794. }
  795. }
  796. else if (in_array($ext, $image_exts))
  797. $target = '<img border="0" alt="'._AT('alternate_text').'" src="'.$row['secondary_resource'].'"/>';
  798. // otherwise
  799. else
  800. $target = '<p><a href="'.$row['secondary_resource'].'">'.$row['secondary_resource'].'</a></p>';
  801. // replace or append the target alternative to the source
  802. if (($row['primary_type']==3 && $_SESSION['prefs']['PREF_ALT_TO_TEXT_APPEND_OR_REPLACE'] == 'replace') ||
  803. ($row['primary_type']==1 && $_SESSION['prefs']['PREF_ALT_TO_AUDIO_APPEND_OR_REPLACE']=='replace') ||
  804. ($row['primary_type']==4 && $_SESSION['prefs']['PREF_ALT_TO_VISUAL_APPEND_OR_REPLACE']=='replace'))
  805. $pattern_replace_to = '${1}'."\n".$target."\n".'${3}';
  806. else
  807. $pattern_replace_to = '${1}${2}'."<br /><br />\n".$target."\n".'${3}';
  808. // *** Alternative replace/append starts from here ***
  809. $processed = false; // one primary resource is only processed once
  810. // append/replace target alternative to [media]source[/media]
  811. if (!$processed && preg_match("/".preg_quote("[media").".*".preg_quote("]".$row['resource']."[/media]", "/")."/sU", $content))
  812. {
  813. $processed = true;
  814. if (!$info_only) {
  815. $content = preg_replace("/(.*)(".preg_quote("[media").".*".preg_quote("]".$row['resource']."[/media]", "/").")(.*)/sU",
  816. $pattern_replace_to, $content);
  817. } else {
  818. if ($row['secondary_type'] == 1) $has_audio_alternative = true;
  819. if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
  820. if ($row['secondary_type'] == 3) $has_text_alternative = true;
  821. if ($row['secondary_type'] == 4) $has_visual_alternative = true;
  822. }
  823. }
  824. // append/replace target alternative to <img ... src="source" ...></a>
  825. if (!$processed && preg_match("/\<img.*src=\"".preg_quote($row['resource'], "/")."\".*\/\>/sU", $content))
  826. {
  827. $processed = true;
  828. if (!$info_only) {
  829. $content = preg_replace("/(.*)(\<img.*src=\"".preg_quote($row['resource'], "/")."\".*\/\>)(.*)/sU",
  830. $pattern_replace_to, $content);
  831. } else {
  832. if ($row['secondary_type'] == 1) $has_audio_alternative = true;
  833. if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
  834. if ($row['secondary_type'] == 3) $has_text_alternative = true;
  835. if ($row['secondary_type'] == 4) $has_visual_alternative = true;
  836. }
  837. }
  838. // append/replace target alternative to <object ... source ...></object>
  839. if (!$processed && preg_match("/\<object.*".preg_quote($row['resource'], "/").".*\<\/object\>/sU", $content))
  840. {
  841. $processed = true;
  842. if (!$info_only) {
  843. $content = preg_replace("/(.*)(\<object.*".preg_quote($row['resource'], "/").".*\<\/object\>)(.*)/sU",
  844. $pattern_replace_to, $content);
  845. } else {
  846. if ($row['secondary_type'] == 1) $has_audio_alternative = true;
  847. if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
  848. if ($row['secondary_type'] == 3) $has_text_alternative = true;
  849. if ($row['secondary_type'] == 4) $has_visual_alternative = true;
  850. }
  851. }
  852. // append/replace target alternative to <a>...source...</a> or <a ...source...>...</a>
  853. // skip this "if" when the source object has been processed in aboved <img> tag
  854. if (!$processed && preg_match("/\<a.*".preg_quote($row['resource'], "/").".*\<\/a\>/sU", $content))
  855. {
  856. $processed = true;
  857. if (!$info_only) {
  858. $content = preg_replace("/(.*)(\<a.*".preg_quote($row['resource'], "/").".*\<\/a\>)(.*)/sU",
  859. $pattern_replace_to, $content);
  860. } else {
  861. if ($row['secondary_type'] == 1) $has_audio_alternative = true;
  862. if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
  863. if ($row['secondary_type'] == 3) $has_text_alternative = true;
  864. if ($row['secondary_type'] == 4) $has_visual_alternative = true;
  865. }
  866. }
  867. // append/replace target alternative to <embed ... source ...>
  868. if (!$processed && preg_match("/\<embed.*".preg_quote($row['resource'], "/").".*\>/sU", $content))
  869. {
  870. $processed = true;
  871. if (!$info_only) {
  872. $content = preg_replace("/(.*)(\<embed.*".preg_quote($row['resource'], "/").".*\>)(.*)/sU",
  873. $pattern_replace_to, $content);
  874. } else {
  875. if ($row['secondary_type'] == 1) $has_audio_alternative = true;
  876. if ($row['secondary_type'] == 2) $has_sign_lang_alternative = true;
  877. if ($row['secondary_type'] == 3) $has_text_alternative = true;
  878. if ($row['secondary_type'] == 4) $has_visual_alternative = true;
  879. }
  880. }
  881. }
  882. }
  883. if (!$info_only) {
  884. return $content;
  885. } else {
  886. return array($has_text_alternative, $has_audio_alternative, $has_visual_alternative, $has_sign_lang_alternative);
  887. }
  888. }
  889. /**
  890. * This function save the last content_id accessed by current user on a course into db and set $_SESSION['s_cid']
  891. * @access: public
  892. * @param: $content_id
  893. * @return: save $content_id, the last visited one of the current user, into db and session
  894. */
  895. public static function saveLastCid($content_id)
  896. {
  897. global $_course_id;
  898. if (!$content_id || !isset($_SESSION['user_id'])) return;
  899. include_once(TR_INCLUDE_PATH.'classes/DAO/UserCoursesDAO.class.php');
  900. $userCoursesDAO = new UserCoursesDAO();
  901. if ($userCoursesDAO->isExist($_SESSION['user_id'], $_course_id))
  902. {
  903. $userCoursesDAO->UpdateLastCid($_SESSION['user_id'], $_course_id, $content_id);
  904. $_SESSION['s_cid'] = $content_id;
  905. }
  906. }
  907. }
  908. ?>