text.lib.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * This is the text library for Chamilo.
  5. * It is loaded during the global initialization,
  6. * so the functions below are available everywhere.
  7. *
  8. * @package chamilo.library
  9. */
  10. define('EXERCISE_NUMBER_OF_DECIMALS', 2);
  11. /**
  12. * This function strips all html-tags found in the input string and outputs a pure text.
  13. * Mostly, the function is to be used before language or encoding detection of the input string.
  14. * @param string $string The input string with html-tags to be converted to plain text.
  15. * @return string The returned plain text as a result.
  16. */
  17. function api_html_to_text($string)
  18. {
  19. // These purifications have been found experimentally, for nice looking output.
  20. $string = preg_replace('/<br[^>]*>/i', "\n", $string);
  21. $string = preg_replace('/<\/?(div|p|h[1-6]|table|ol|ul|blockquote)[^>]*>/i', "\n", $string);
  22. $string = preg_replace('/<\/(tr|li)[^>]*>/i', "\n", $string);
  23. $string = preg_replace('/<\/(td|th)[^>]*>/i', "\t", $string);
  24. $string = strip_tags($string);
  25. // Line endings unification and cleaning.
  26. $string = str_replace(array("\r\n", "\n\r", "\r"), "\n", $string);
  27. $string = preg_replace('/\s*\n/', "\n", $string);
  28. $string = preg_replace('/\n+/', "\n", $string);
  29. return trim($string);
  30. }
  31. /**
  32. * Detects encoding of html-formatted text.
  33. * @param string $string The input html-formatted text.
  34. * @return string Returns the detected encoding.
  35. */
  36. function api_detect_encoding_html($string) {
  37. if (@preg_match('/<head.*(<meta[^>]*content=[^>]*>).*<\/head>/si', $string, $matches)) {
  38. if (@preg_match('/<meta[^>]*charset=(.*)["\';][^>]*>/si', $matches[1], $matches)) {
  39. return api_refine_encoding_id(trim($matches[1]));
  40. }
  41. }
  42. return api_detect_encoding(api_html_to_text($string));
  43. }
  44. /**
  45. * Converts the text of a html-document to a given encoding, the meta-tag is changed accordingly.
  46. * @param string $string The input full-html document.
  47. * @param string The new encoding value to be set.
  48. */
  49. function api_set_encoding_html(&$string, $encoding) {
  50. $old_encoding = api_detect_encoding_html($string);
  51. if (@preg_match('/(.*<head.*)(<meta[^>]*content=[^>]*>)(.*<\/head>.*)/si', $string, $matches)) {
  52. $meta = $matches[2];
  53. if (@preg_match("/(<meta[^>]*charset=)(.*)([\"';][^>]*>)/si", $meta, $matches1)) {
  54. $meta = $matches1[1] . $encoding . $matches1[3];
  55. $string = $matches[1] . $meta . $matches[3];
  56. } else {
  57. $string = $matches[1] . '<meta http-equiv="Content-Type" content="text/html; charset='.$encoding.'"/>' . $matches[3];
  58. }
  59. } else {
  60. $count = 1;
  61. $string = str_ireplace('</head>', '<meta http-equiv="Content-Type" content="text/html; charset='.$encoding.'"/></head>', $string, $count);
  62. }
  63. $string = api_convert_encoding($string, $encoding, $old_encoding);
  64. }
  65. /**
  66. * Returns the title of a html document.
  67. * @param string $string The contents of the input document.
  68. * @param string $input_encoding The encoding of the input document. If the value is not set, it is detected.
  69. * @param string $$output_encoding The encoding of the retrieved title. If the value is not set, the system encoding is assumend.
  70. * @return string The retrieved title, html-entities and extra-whitespace between the words are cleaned.
  71. */
  72. function api_get_title_html(&$string, $output_encoding = null, $input_encoding = null) {
  73. if (@preg_match('/<head.+<title[^>]*>(.*)<\/title>/msi', $string, $matches)) {
  74. if (empty($output_encoding)) {
  75. $output_encoding = api_get_system_encoding();
  76. }
  77. if (empty($input_encoding)) {
  78. $input_encoding = api_detect_encoding_html($string);
  79. }
  80. return trim(@preg_replace('/\s+/', ' ', api_html_entity_decode(api_convert_encoding($matches[1], $output_encoding, $input_encoding), ENT_QUOTES, $output_encoding)));
  81. }
  82. return '';
  83. }
  84. /* XML processing functions */
  85. // A regular expression for accessing declared encoding within xml-formatted text.
  86. // Published by Steve Minutillo,
  87. // http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss/
  88. define('_PCRE_XML_ENCODING', '/<\?xml.*encoding=[\'"](.*?)[\'"].*\?>/m');
  89. /**
  90. * Detects encoding of xml-formatted text.
  91. * @param string $string The input xml-formatted text.
  92. * @param string $default_encoding This is the default encoding to be returned if there is no way the xml-text's encoding to be detected. If it not spesified, the system encoding is assumed then.
  93. * @return string Returns the detected encoding.
  94. * @todo The second parameter is to be eliminated. See api_detect_encoding_html().
  95. */
  96. function api_detect_encoding_xml($string, $default_encoding = null) {
  97. if (preg_match(_PCRE_XML_ENCODING, $string, $matches)) {
  98. return api_refine_encoding_id($matches[1]);
  99. }
  100. if (api_is_valid_utf8($string)) {
  101. return 'UTF-8';
  102. }
  103. if (empty($default_encoding)) {
  104. $default_encoding = _api_mb_internal_encoding();
  105. }
  106. return api_refine_encoding_id($default_encoding);
  107. }
  108. /**
  109. * Converts character encoding of a xml-formatted text. If inside the text the encoding is declared, it is modified accordingly.
  110. * @param string $string The text being converted.
  111. * @param string $to_encoding The encoding that text is being converted to.
  112. * @param string $from_encoding (optional) The encoding that text is being converted from. If it is omited, it is tried to be detected then.
  113. * @return string Returns the converted xml-text.
  114. */
  115. function api_convert_encoding_xml($string, $to_encoding, $from_encoding = null) {
  116. return _api_convert_encoding_xml($string, $to_encoding, $from_encoding);
  117. }
  118. /**
  119. * Converts character encoding of a xml-formatted text into UTF-8. If inside the text the encoding is declared, it is set to UTF-8.
  120. * @param string $string The text being converted.
  121. * @param string $from_encoding (optional) The encoding that text is being converted from. If it is omited, it is tried to be detected then.
  122. * @return string Returns the converted xml-text.
  123. */
  124. function api_utf8_encode_xml($string, $from_encoding = null) {
  125. return _api_convert_encoding_xml($string, 'UTF-8', $from_encoding);
  126. }
  127. /**
  128. * Converts character encoding of a xml-formatted text from UTF-8 into a specified encoding. If inside the text the encoding is declared, it is modified accordingly.
  129. * @param string $string The text being converted.
  130. * @param string $to_encoding (optional) The encoding that text is being converted to. If it is omited, the platform character set is assumed.
  131. * @return string Returns the converted xml-text.
  132. */
  133. function api_utf8_decode_xml($string, $to_encoding = null) {
  134. if (empty($to_encoding)) {
  135. $to_encoding = _api_mb_internal_encoding();
  136. }
  137. return _api_convert_encoding_xml($string, $to_encoding, 'UTF-8');
  138. }
  139. /**
  140. * Converts character encoding of a xml-formatted text. If inside the text the encoding is declared, it is modified accordingly.
  141. * @param string $string The text being converted.
  142. * @param string $to_encoding The encoding that text is being converted to.
  143. * @param string $from_encoding (optional) The encoding that text is being converted from. If the value is empty, it is tried to be detected then.
  144. * @return string Returns the converted xml-text.
  145. */
  146. function _api_convert_encoding_xml(&$string, $to_encoding, $from_encoding) {
  147. if (empty($from_encoding)) {
  148. $from_encoding = api_detect_encoding_xml($string);
  149. }
  150. $to_encoding = api_refine_encoding_id($to_encoding);
  151. if (!preg_match('/<\?xml.*\?>/m', $string, $matches)) {
  152. return api_convert_encoding('<?xml version="1.0" encoding="'.$to_encoding.'"?>'."\n".$string, $to_encoding, $from_encoding);
  153. }
  154. if (!preg_match(_PCRE_XML_ENCODING, $string)) {
  155. if (strpos($matches[0], 'standalone') !== false) {
  156. // The encoding option should precede the standalone option, othewise DOMDocument fails to load the document.
  157. $replace = str_replace('standalone', ' encoding="'.$to_encoding.'" standalone' , $matches[0]);
  158. } else {
  159. $replace = str_replace('?>', ' encoding="'.$to_encoding.'"?>' , $matches[0]);
  160. }
  161. return api_convert_encoding(str_replace($matches[0], $replace, $string), $to_encoding, $from_encoding);
  162. }
  163. global $_api_encoding;
  164. $_api_encoding = api_refine_encoding_id($to_encoding);
  165. return api_convert_encoding(preg_replace_callback(_PCRE_XML_ENCODING, '_api_convert_encoding_xml_callback', $string), $to_encoding, $from_encoding);
  166. }
  167. /**
  168. * A callback for serving the function _api_convert_encoding_xml().
  169. * @param array $matches Input array of matches corresponding to the xml-declaration.
  170. * @return string Returns the xml-declaration with modified encoding.
  171. */
  172. function _api_convert_encoding_xml_callback($matches) {
  173. global $_api_encoding;
  174. return str_replace($matches[1], $_api_encoding, $matches[0]);
  175. }
  176. /* CSV processing functions */
  177. /**
  178. * Parses CSV data (one line) into an array. This function is not affected by the OS-locale settings.
  179. * @param string $string The input string.
  180. * @param string $delimiter (optional) The field delimiter, one character only. The default delimiter character is comma {,).
  181. * @param string $enclosure (optional) The field enclosure, one character only. The default enclosure character is quote (").
  182. * @param string $escape (optional) The escape character, one character only. The default escape character is backslash (\).
  183. * @return array Returns an array containing the fields read.
  184. * Note: In order this function to work correctly with UTF-8, limitation for the parameters $delimiter, $enclosure and $escape
  185. * should be kept. These parameters should be single ASCII characters only. Thus the implementation of this function is faster.
  186. * @link http://php.net/manual/en/function.str-getcsv.php (exists as of PHP 5 >= 5.3.0)
  187. */
  188. function & api_str_getcsv(& $string, $delimiter = ',', $enclosure = '"', $escape = '\\') {
  189. $delimiter = (string)$delimiter;
  190. if (api_byte_count($delimiter) > 1) { $delimiter = $delimiter[1]; }
  191. $enclosure = (string)$enclosure;
  192. if (api_byte_count($enclosure) > 1) { $enclosure = $enclosure[1]; }
  193. $escape = (string)$escape;
  194. if (api_byte_count($escape) > 1) { $escape = $escape[1]; }
  195. $str = (string)$string;
  196. $len = api_byte_count($str);
  197. $enclosed = false;
  198. $escaped = false;
  199. $value = '';
  200. $result = array();
  201. for ($i = 0; $i < $len; $i++) {
  202. $char = $str[$i];
  203. if ($char == $escape) {
  204. if (!$escaped) {
  205. $escaped = true;
  206. continue;
  207. }
  208. }
  209. $escaped = false;
  210. switch ($char) {
  211. case $enclosure:
  212. if ($enclosed && $str[$i + 1] == $enclosure) {
  213. $value .= $char;
  214. $i++;
  215. } else {
  216. $enclosed = !$enclosed;
  217. }
  218. break;
  219. case $delimiter:
  220. if (!$enclosed) {
  221. $result[] = $value;
  222. $value = '';
  223. } else {
  224. $value .= $char;
  225. }
  226. break;
  227. default:
  228. $value .= $char;
  229. break;
  230. }
  231. }
  232. if (!empty($value)) {
  233. $result[] = $value;
  234. }
  235. return $result;
  236. }
  237. /**
  238. * Reads a line from a file pointer and parses it for CSV fields. This function is not affected by the OS-locale settings.
  239. * @param resource $handle The file pointer, it must be valid and must point to a file successfully opened by fopen().
  240. * @param int $length (optional) Reading ends when length - 1 bytes have been read, on a newline (which is included in the return value), or on EOF (whichever comes first).
  241. * If no length is specified, it will keep reading from the stream until it reaches the end of the line.
  242. * @param string $delimiter (optional) The field delimiter, one character only. The default delimiter character is comma {,).
  243. * @param string $enclosure (optional) The field enclosure, one character only. The default enclosure character is quote (").
  244. * @param string $escape (optional) The escape character, one character only. The default escape character is backslash (\).
  245. * @return array Returns an array containing the fields read.
  246. * Note: In order this function to work correctly with UTF-8, limitation for the parameters $delimiter, $enclosure and $escape
  247. * should be kept. These parameters should be single ASCII characters only.
  248. * @link http://php.net/manual/en/function.fgetcsv.php
  249. */
  250. function api_fgetcsv($handle, $length = null, $delimiter = ',', $enclosure = '"', $escape = '\\') {
  251. if (($line = is_null($length) ? fgets($handle): fgets($handle, $length)) !== false) {
  252. $line = rtrim($line, "\r\n");
  253. return api_str_getcsv($line, $delimiter, $enclosure, $escape);
  254. }
  255. return false;
  256. }
  257. /* Functions for supporting ASCIIMathML mathematical formulas and ASCIIsvg maathematical graphics */
  258. /**
  259. * Dectects ASCIIMathML formula presence within a given html text.
  260. * @param string $html The input html text.
  261. * @return bool Returns TRUE when there is a formula found or FALSE otherwise.
  262. */
  263. function api_contains_asciimathml($html) {
  264. if (!preg_match_all('/<span[^>]*class\s*=\s*[\'"](.*?)[\'"][^>]*>/mi', $html, $matches)) {
  265. return false;
  266. }
  267. foreach ($matches[1] as $string) {
  268. $string = ' '.str_replace(',', ' ', $string).' ';
  269. if (preg_match('/\sAM\s/m', $string)) {
  270. return true;
  271. }
  272. }
  273. return false;
  274. }
  275. /**
  276. * Dectects ASCIIsvg graphics presence within a given html text.
  277. * @param string $html The input html text.
  278. * @return bool Returns TRUE when there is a graph found or FALSE otherwise.
  279. */
  280. function api_contains_asciisvg($html) {
  281. if (!preg_match_all('/<embed([^>]*?)>/mi', $html, $matches)) {
  282. return false;
  283. }
  284. foreach ($matches[1] as $string) {
  285. $string = ' '.str_replace(',', ' ', $string).' ';
  286. if (preg_match('/sscr\s*=\s*[\'"](.*?)[\'"]/m', $string)) {
  287. return true;
  288. }
  289. }
  290. return false;
  291. }
  292. /* Miscellaneous text processing functions */
  293. /**
  294. * Convers a string from camel case into underscore.
  295. * Works correctly with ASCII strings only, implementation for human-language strings is not necessary.
  296. * @param string $string The input string (ASCII)
  297. * @return string The converted result string
  298. */
  299. function api_camel_case_to_underscore($string) {
  300. return strtolower(preg_replace('/([a-z])([A-Z])/', "$1_$2", $string));
  301. }
  302. /**
  303. * Converts a string with underscores into camel case.
  304. * Works correctly with ASCII strings only, implementation for human-language strings is not necessary.
  305. * @param string $string The input string (ASCII)
  306. * @param bool $capitalise_first_char (optional) If true (default), the function capitalises the first char in the result string.
  307. * @return string The converted result string
  308. */
  309. function api_underscore_to_camel_case($string, $capitalise_first_char = true) {
  310. if ($capitalise_first_char) {
  311. $string = ucfirst($string);
  312. }
  313. return preg_replace_callback('/_([a-z])/', '_api_camelize', $string);
  314. }
  315. // A function for internal use, only for this library.
  316. function _api_camelize($match) {
  317. return strtoupper($match[1]);
  318. }
  319. /**
  320. * Truncates a string.
  321. *
  322. * @author Brouckaert Olivier
  323. * @param string $text The text to truncate.
  324. * @param integer $length The approximate desired length. The length of the suffix below is to be added to have the total length of the result string.
  325. * @param string $suffix A suffix to be added as a replacement.
  326. * @param string $encoding (optional) The encoding to be used. If it is omitted, the platform character set will be used by default.
  327. * @param boolean $middle If this parameter is true, truncation is done in the middle of the string.
  328. * @return string Truncated string, decorated with the given suffix (replacement).
  329. */
  330. function api_trunc_str($text, $length = 30, $suffix = '...', $middle = false, $encoding = null) {
  331. if (empty($encoding)) {
  332. $encoding = api_get_system_encoding();
  333. }
  334. $text_length = api_strlen($text, $encoding);
  335. if ($text_length <= $length) {
  336. return $text;
  337. }
  338. if ($middle) {
  339. return rtrim(api_substr($text, 0, round($length / 2), $encoding)).$suffix.ltrim(api_substr($text, - round($length / 2), $text_length, $encoding));
  340. }
  341. return rtrim(api_substr($text, 0, $length, $encoding)).$suffix;
  342. }
  343. /**
  344. * Handling simple and double apostrofe in order that strings be stored properly in database
  345. *
  346. * @author Denes Nagy
  347. * @param string variable - the variable to be revised
  348. */
  349. function domesticate($input) {
  350. $input = stripslashes($input);
  351. $input = str_replace("'", "''", $input);
  352. $input = str_replace('"', "''", $input);
  353. return ($input);
  354. }
  355. /**
  356. * function make_clickable($string)
  357. *
  358. * @desc Completes url contained in the text with "<a href ...".
  359. * However the function simply returns the submitted text without any
  360. * transformation if it already contains some "<a href:" or "<img src=".
  361. * @param string $text text to be converted
  362. * @return text after conversion
  363. * @author Rewritten by Nathan Codding - Feb 6, 2001.
  364. * completed by Hugues Peeters - July 22, 2002
  365. *
  366. * Actually this function is taken from the PHP BB 1.4 script
  367. * - Goes through the given string, and replaces xxxx://yyyy with an HTML <a> tag linking
  368. * to that URL
  369. * - Goes through the given string, and replaces www.xxxx.yyyy[zzzz] with an HTML <a> tag linking
  370. * to http://www.xxxx.yyyy[/zzzz]
  371. * - Goes through the given string, and replaces xxxx@yyyy with an HTML mailto: tag linking
  372. * to that email address
  373. * - Only matches these 2 patterns either after a space, or at the beginning of a line
  374. *
  375. * Notes: the email one might get annoying - it's easy to make it more restrictive, though.. maybe
  376. * have it require something like xxxx@yyyy.zzzz or such. We'll see.
  377. */
  378. function make_clickable($string) {
  379. // TODO: eregi_replace() is deprecated as of PHP 5.3
  380. if (!stristr($string, ' src=') && !stristr($string, ' href=')) {
  381. $string = eregi_replace("(https?|ftp)://([a-z0-9#?/&=._+:~%-]+)", "<a href=\"\\1://\\2\" target=\"_blank\">\\1://\\2</a>", $string);
  382. $string = eregi_replace("([a-z0-9_.-]+@[a-z0-9.-]+)", "<a href=\"mailto:\\1\">\\1</a>", $string);
  383. }
  384. return $string;
  385. }
  386. /**
  387. * @desc This function does some parsing on the text that gets inputted. This parsing can be of any kind
  388. * LaTeX notation, Word Censoring, Glossary Terminology (extension will available soon), Musical Notations, ...
  389. * The inspiration for this filter function came from Moodle an phpBB who both use a similar approach.
  390. * <code>[tex]\sqrt(2)[/tex]</code>
  391. * @param $input string. some text
  392. * @return $output string. some text that contains the parsed elements.
  393. * @author Patrick Cool <patrick.cool@UGent.be>
  394. * @version March 2OO6
  395. */
  396. function text_filter($input, $filter = true) {
  397. //$input = stripslashes($input);
  398. if ($filter) {
  399. // *** parse [tex]...[/tex] tags *** //
  400. // which will return techexplorer or image html depending on the capabilities of the
  401. // browser of the user (using some javascript that checks if the browser has the TechExplorer plugin installed or not)
  402. //$input = _text_parse_tex($input);
  403. // *** parse [teximage]...[/teximage] tags *** //
  404. // these force the gif rendering of LaTeX using the mimetex gif renderer
  405. //$input=_text_parse_tex_image($input);
  406. // *** parse [texexplorer]...[/texexplorer] tags *** //
  407. // these force the texeplorer LaTeX notation
  408. //$input = _text_parse_texexplorer($input);
  409. // *** Censor Words *** //
  410. // censor words. This function removes certain words by [censored]
  411. // this can be usefull when the campus is open to the world.
  412. // $input=text_censor_words($input);
  413. // *** parse [?]...[/?] tags *** //
  414. // for the glossary tool
  415. //$input = _text_parse_glossary($input);
  416. // parse [wiki]...[/wiki] tags
  417. // this is for the coolwiki plugin.
  418. // $input=text_parse_wiki($input);
  419. // parse [tool]...[/tool] tags
  420. // this parse function adds a link to a certain tool
  421. // $input=text_parse_tool($input);
  422. // parse [user]...[/user] tags
  423. // parse [email]...[/email] tags
  424. // parse [code]...[/code] tags
  425. }
  426. return $input;
  427. }
  428. /**
  429. * Applies parsing for tex commands that are separated by [tex]
  430. * [/tex] to make it readable for techexplorer plugin.
  431. * This function should not be accessed directly but should be accesse through the text_filter function
  432. * @param string $text The text to parse
  433. * @return string The text after parsing.
  434. * @author Patrick Cool <patrick.cool@UGent.be>
  435. * @version June 2004
  436. */
  437. function _text_parse_tex($textext) {
  438. //$textext = str_replace(array ("[tex]", "[/tex]"), array ('[*****]', '[/*****]'), $textext);
  439. //$textext = stripslashes($texttext);
  440. $input_array = preg_split("/(\[tex]|\[\/tex])/", $textext, -1, PREG_SPLIT_DELIM_CAPTURE);
  441. foreach ($input_array as $key => $value) {
  442. if ($key > 0 && $input_array[$key - 1] == '[tex]' AND $input_array[$key + 1] == '[/tex]') {
  443. $input_array[$key] = latex_gif_renderer($value);
  444. unset($input_array[$key - 1]);
  445. unset($input_array[$key + 1]);
  446. //echo 'LaTeX: <embed type="application/x-techexplorer" texdata="'.stripslashes($value).'" autosize="true" pluginspage="http://www.integretechpub.com/techexplorer/"><br />';
  447. }
  448. }
  449. $output = implode('',$input_array);
  450. return $output;
  451. }
  452. /**
  453. * This function should not be accessed directly but should be accesse through the text_filter function
  454. * @author Patrick Cool <patrick.cool@UGent.be>
  455. */
  456. function _text_parse_glossary($input) {
  457. return $input;
  458. }
  459. /**
  460. * @desc This function makes a valid link to a different tool.
  461. * This function should not be accessed directly but should be accesse through the text_filter function
  462. * @author Patrick Cool <patrick.cool@UGent.be>
  463. */
  464. function _text_parse_tool($input) {
  465. // An array with all the valid tools
  466. $tools[] = array(TOOL_ANNOUNCEMENT, 'announcements/announcements.php');
  467. $tools[] = array(TOOL_CALENDAR_EVENT, 'calendar/agenda.php');
  468. // Check if the name between the [tool] [/tool] tags is a valid one
  469. }
  470. /**
  471. * Renders LaTeX code into a gif or retrieve a cached version of the gif.
  472. * @author Patrick Cool <patrick.cool@UGent.be> Ghent University
  473. */
  474. function latex_gif_renderer($latex_code) {
  475. global $_course;
  476. // Setting the paths and filenames
  477. $mimetex_path = api_get_path(LIBRARY_PATH).'mimetex/';
  478. $temp_path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/temp/';
  479. $latex_filename = md5($latex_code).'.gif';
  480. if (!file_exists($temp_path.$latex_filename) OR isset($_GET['render'])) {
  481. if (IS_WINDOWS_OS) {
  482. $mimetex_command = $mimetex_path.'mimetex.exe -e "'.$temp_path.md5($latex_code).'.gif" '.escapeshellarg($latex_code).'';
  483. } else {
  484. $mimetex_command = $mimetex_path.'mimetex.cgi -e "'.$temp_path.md5($latex_code).'.gif" '.escapeshellarg($latex_code);
  485. }
  486. exec($mimetex_command);
  487. //echo 'volgende shell commando werd uitgevoerd:<br /><pre>'.$mimetex_command.'</pre><hr>';
  488. }
  489. $return = "<a href=\"\" onclick=\"javascript: newWindow=window.open('".api_get_path(WEB_CODE_PATH)."inc/latex.php?code=".urlencode($latex_code)."&amp;filename=$latex_filename','latexCode','toolbar=no,location=no,scrollbars=yes,resizable=yes,status=yes,width=375,height=250,left=200,top=100');\">";
  490. $return .= '<img src="'.api_get_path(WEB_COURSE_PATH).$_course['path'].'/temp/'.$latex_filename.'" alt="'.$latex_code.'" border="0" /></a>';
  491. return $return;
  492. }
  493. /**
  494. * This functions cuts a paragraph
  495. * i.e cut('Merry Xmas from Lima',13) = "Merry Xmas fr..."
  496. * @param string The text to "cut"
  497. * @param int Count of chars
  498. * @param bool Whether to embed in a <span title="...">...</span>
  499. * @return string
  500. * */
  501. function cut($text, $maxchar, $embed = false) {
  502. if (api_strlen($text) > $maxchar) {
  503. if ($embed) {
  504. return '<span title="'.$text.'">'.api_substr($text, 0, $maxchar).'...</span>';
  505. }
  506. return api_substr($text, 0, $maxchar).' ...';
  507. }
  508. return $text;
  509. }
  510. /**
  511. * Show a number as only integers if no decimals, but will show 2 decimals if exist.
  512. *
  513. * @param mixed Number to convert
  514. * @param int Decimal points 0=never, 1=if needed, 2=always
  515. * @return mixed An integer or a float depends on the parameter
  516. */
  517. function float_format($number, $flag = 1) {
  518. if (is_numeric($number)) {
  519. if (!$number) {
  520. $result = ($flag == 2 ? '0.'.str_repeat('0', EXERCISE_NUMBER_OF_DECIMALS) : '0');
  521. } else {
  522. if (floor($number) == $number) {
  523. $result = number_format($number, ($flag == 2 ? EXERCISE_NUMBER_OF_DECIMALS : 0));
  524. } else {
  525. $result = number_format(round($number, 2), ($flag == 0 ? 0 : EXERCISE_NUMBER_OF_DECIMALS));
  526. }
  527. }
  528. return $result;
  529. }
  530. }
  531. // TODO: To be checked for correct timezone management.
  532. /**
  533. * Function to obtain last week timestamps
  534. * @return array Times for every day inside week
  535. */
  536. function get_last_week() {
  537. $week = date('W');
  538. $year = date('Y');
  539. $lastweek = $week - 1;
  540. if ($lastweek == 0) {
  541. $week = 52;
  542. $year--;
  543. }
  544. $lastweek = sprintf("%02d", $lastweek);
  545. $arrdays = array();
  546. for ($i = 1; $i <= 7; $i++) {
  547. $arrdays[] = strtotime("$year"."W$lastweek"."$i");
  548. }
  549. return $arrdays;
  550. }
  551. /**
  552. * Gets the week from a day
  553. * @param string Date in UTC (2010-01-01 12:12:12)
  554. * @return int Returns an integer with the week number of the year
  555. */
  556. function get_week_from_day($date) {
  557. if (!empty($date)) {
  558. $time = api_strtotime($date,'UTC');
  559. return date('W', $time);
  560. } else {
  561. return date('W');
  562. }
  563. }
  564. /**
  565. * Deprecated functions
  566. */
  567. /**
  568. * Applies parsing the content for tex commands that are separated by [tex]
  569. * [/tex] to make it readable for techexplorer plugin.
  570. * @param string $text The text to parse
  571. * @return string The text after parsing.
  572. * @author Patrick Cool <patrick.cool@UGent.be>
  573. * @version June 2004
  574. */
  575. function api_parse_tex($textext) {
  576. /*
  577. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
  578. return str_replace(array('[tex]', '[/tex]'), array("<object classid=\"clsid:5AFAB315-AD87-11D3-98BB-002035EFB1A4\"><param name=\"autosize\" value=\"true\" /><param name=\"DataType\" value=\"0\" /><param name=\"Data\" value=\"", "\" /></object>"), $textext);
  579. }
  580. return str_replace(array('[tex]', '[/tex]'), array("<embed type=\"application/x-techexplorer\" texdata=\"", "\" autosize=\"true\" pluginspage=\"http://www.integretechpub.com/techexplorer/\">"), $textext);
  581. */
  582. return $textext;
  583. }
  584. /**
  585. * Applies parsing for tex commandos that are seperated by [tex]
  586. * [/tex] to make it readable for techexplorer plugin.
  587. * This function should not be accessed directly but should be accesse through the text_filter function
  588. * @param string $text The text to parse
  589. * @return string The text after parsing.
  590. * @author Patrick Cool <patrick.cool@UGent.be>
  591. * @version June 2004
  592. */
  593. function _text_parse_texexplorer($textext) {
  594. /*
  595. if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  596. $textext = str_replace(array("[texexplorer]", "[/texexplorer]"), array("<object classid=\"clsid:5AFAB315-AD87-11D3-98BB-002035EFB1A4\"><param name=\"autosize\" value=\"true\" /><param name=\"DataType\" value=\"0\" /><param name=\"Data\" value=\"", "\" /></object>"), $textext);
  597. } else {
  598. $textext = str_replace(array("[texexplorer]", "[/texexplorer]"), array("<embed type=\"application/x-techexplorer\" texdata=\"", "\" autosize=\"true\" pluginspage=\"http://www.integretechpub.com/techexplorer/\">"), $textext);
  599. }
  600. return $textext;
  601. */
  602. return $textext;
  603. }
  604. /**
  605. * This function splits the string into words and then joins them back together again one by one.
  606. * Example: "Test example of a long string"
  607. * substrwords(5) = Test ... *
  608. * @param string
  609. * @param int the max number of character
  610. * @param string how the string will be end
  611. * @return a reduce string
  612. */
  613. function substrwords($text,$maxchar,$end='...')
  614. {
  615. if(strlen($text)>$maxchar)
  616. {
  617. $words=explode(" ",$text);
  618. $output = '';
  619. $i=0;
  620. while(1)
  621. {
  622. $length = (strlen($output)+strlen($words[$i]));
  623. if($length>$maxchar)
  624. {
  625. break;
  626. }
  627. else
  628. {
  629. $output = $output." ".$words[$i];
  630. $i++;
  631. };
  632. };
  633. }
  634. else
  635. {
  636. $output = $text;
  637. return $output;
  638. }
  639. return $output.$end;
  640. }
  641. function implode_with_key($glue, $array) {
  642. if (!empty($array)) {
  643. $string = '';
  644. foreach($array as $key => $value) {
  645. if (empty($value)) {
  646. $value = 'null';
  647. }
  648. $string .= $key." : ".$value." $glue ";
  649. }
  650. return $string;
  651. }
  652. return '';
  653. }
  654. /**
  655. * Transform the file size in a human readable format.
  656. *
  657. * @param int $file_size Size of the file in bytes
  658. * @return string A human readable representation of the file size
  659. */
  660. function format_file_size($file_size)
  661. {
  662. $file_size = intval($file_size);
  663. if ($file_size >= 1073741824) {
  664. $file_size = round($file_size / 1073741824 * 100) / 100 . 'G';
  665. } elseif($file_size >= 1048576) {
  666. $file_size = round($file_size / 1048576 * 100) / 100 . 'M';
  667. } elseif($file_size >= 1024) {
  668. $file_size = round($file_size / 1024 * 100) / 100 . 'k';
  669. } else {
  670. $file_size = $file_size . 'B';
  671. }
  672. return $file_size;
  673. }
  674. function return_datetime_from_array($array)
  675. {
  676. $year = '0000';
  677. $month = $day = $hours = $minutes = $seconds = '00';
  678. if (isset($array['Y']) && (isset($array['F']) || isset($array['M'])) && isset($array['d']) && isset($array['H']) && isset($array['i'])) {
  679. $year = $array['Y'];
  680. $month = isset($array['F'])?$array['F']:$array['M'];
  681. if (intval($month) < 10 ) $month = '0'.$month;
  682. $day = $array['d'];
  683. if (intval($day) < 10 ) $day = '0'.$day;
  684. $hours = $array['H'];
  685. if (intval($hours) < 10 ) $hours = '0'.$hours;
  686. $minutes = $array['i'];
  687. if (intval($minutes) < 10 ) $minutes = '0'.$minutes;
  688. }
  689. if (checkdate($month,$day,$year)) {
  690. $datetime = $year.'-'.$month.'-'.$day.' '.$hours.':'.$minutes.':'.$seconds;
  691. }
  692. return $datetime;
  693. }
  694. /**
  695. * Converts an string CLEANYO[admin][amann,acostea]
  696. * into an array:
  697. *
  698. * array(
  699. * CLEANYO
  700. * admin
  701. * amann,acostea
  702. * )
  703. *
  704. * @param $array
  705. * @return array
  706. */
  707. function bracketsToArray($array)
  708. {
  709. return preg_split('/[\[\]]+/', $array, -1, PREG_SPLIT_NO_EMPTY);
  710. }