PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/weblib.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 1437 lines | 701 code | 153 blank | 583 comment | 172 complexity | 6654c841813de07dae9dcd43b094edc4 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Library of functions for web output
  18. *
  19. * Library of all general-purpose Moodle PHP functions and constants
  20. * that produce HTML output
  21. *
  22. * Other main libraries:
  23. * - datalib.php - functions that access the database.
  24. * - moodlelib.php - general-purpose Moodle functions.
  25. *
  26. * @package core
  27. * @subpackage lib
  28. * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
  29. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30. */
  31. defined('MOODLE_INTERNAL') || die();
  32. /// Constants
  33. /// Define text formatting types ... eventually we can add Wiki, BBcode etc
  34. /**
  35. * Does all sorts of transformations and filtering
  36. */
  37. define('FORMAT_MOODLE', '0'); // Does all sorts of transformations and filtering
  38. /**
  39. * Plain HTML (with some tags stripped)
  40. */
  41. define('FORMAT_HTML', '1'); // Plain HTML (with some tags stripped)
  42. /**
  43. * Plain text (even tags are printed in full)
  44. */
  45. define('FORMAT_PLAIN', '2'); // Plain text (even tags are printed in full)
  46. /**
  47. * Wiki-formatted text
  48. * Deprecated: left here just to note that '3' is not used (at the moment)
  49. * and to catch any latent wiki-like text (which generates an error)
  50. */
  51. define('FORMAT_WIKI', '3'); // Wiki-formatted text
  52. /**
  53. * Markdown-formatted text http://daringfireball.net/projects/markdown/
  54. */
  55. define('FORMAT_MARKDOWN', '4'); // Markdown-formatted text http://daringfireball.net/projects/markdown/
  56. /**
  57. * A moodle_url comparison using this flag will return true if the base URLs match, params are ignored
  58. */
  59. define('URL_MATCH_BASE', 0);
  60. /**
  61. * A moodle_url comparison using this flag will return true if the base URLs match and the params of url1 are part of url2
  62. */
  63. define('URL_MATCH_PARAMS', 1);
  64. /**
  65. * A moodle_url comparison using this flag will return true if the two URLs are identical, except for the order of the params
  66. */
  67. define('URL_MATCH_EXACT', 2);
  68. /// Functions
  69. /**
  70. * Add quotes to HTML characters
  71. *
  72. * Returns $var with HTML characters (like "<", ">", etc.) properly quoted.
  73. * This function is very similar to {@link p()}
  74. *
  75. * @todo Remove obsolete param $obsolete if not used anywhere
  76. *
  77. * @param string $var the string potentially containing HTML characters
  78. * @param boolean $obsolete no longer used.
  79. * @return string
  80. */
  81. function s($var, $obsolete = false) {
  82. if ($var === '0' or $var === false or $var === 0) {
  83. return '0';
  84. }
  85. return preg_replace("/&amp;#(\d+|x[0-7a-fA-F]+);/i", "&#$1;", htmlspecialchars($var, ENT_QUOTES, 'UTF-8', true));
  86. }
  87. /**
  88. * Add quotes to HTML characters
  89. *
  90. * Prints $var with HTML characters (like "<", ">", etc.) properly quoted.
  91. * This function simply calls {@link s()}
  92. * @see s()
  93. *
  94. * @todo Remove obsolete param $obsolete if not used anywhere
  95. *
  96. * @param string $var the string potentially containing HTML characters
  97. * @param boolean $obsolete no longer used.
  98. * @return string
  99. */
  100. function p($var, $obsolete = false) {
  101. echo s($var, $obsolete);
  102. }
  103. /**
  104. * Does proper javascript quoting.
  105. *
  106. * Do not use addslashes anymore, because it does not work when magic_quotes_sybase is enabled.
  107. *
  108. * @param mixed $var String, Array, or Object to add slashes to
  109. * @return mixed quoted result
  110. */
  111. function addslashes_js($var) {
  112. if (is_string($var)) {
  113. $var = str_replace('\\', '\\\\', $var);
  114. $var = str_replace(array('\'', '"', "\n", "\r", "\0"), array('\\\'', '\\"', '\\n', '\\r', '\\0'), $var);
  115. $var = str_replace('</', '<\/', $var); // XHTML compliance
  116. } else if (is_array($var)) {
  117. $var = array_map('addslashes_js', $var);
  118. } else if (is_object($var)) {
  119. $a = get_object_vars($var);
  120. foreach ($a as $key=>$value) {
  121. $a[$key] = addslashes_js($value);
  122. }
  123. $var = (object)$a;
  124. }
  125. return $var;
  126. }
  127. /**
  128. * Remove query string from url
  129. *
  130. * Takes in a URL and returns it without the querystring portion
  131. *
  132. * @param string $url the url which may have a query string attached
  133. * @return string The remaining URL
  134. */
  135. function strip_querystring($url) {
  136. if ($commapos = strpos($url, '?')) {
  137. return substr($url, 0, $commapos);
  138. } else {
  139. return $url;
  140. }
  141. }
  142. /**
  143. * Returns the URL of the HTTP_REFERER, less the querystring portion if required
  144. *
  145. * @uses $_SERVER
  146. * @param boolean $stripquery if true, also removes the query part of the url.
  147. * @return string The resulting referer or empty string
  148. */
  149. function get_referer($stripquery=true) {
  150. if (isset($_SERVER['HTTP_REFERER'])) {
  151. if ($stripquery) {
  152. return strip_querystring($_SERVER['HTTP_REFERER']);
  153. } else {
  154. return $_SERVER['HTTP_REFERER'];
  155. }
  156. } else {
  157. return '';
  158. }
  159. }
  160. /**
  161. * Returns the name of the current script, WITH the querystring portion.
  162. *
  163. * This function is necessary because PHP_SELF and REQUEST_URI and SCRIPT_NAME
  164. * return different things depending on a lot of things like your OS, Web
  165. * server, and the way PHP is compiled (ie. as a CGI, module, ISAPI, etc.)
  166. * <b>NOTE:</b> This function returns false if the global variables needed are not set.
  167. *
  168. * @return mixed String, or false if the global variables needed are not set
  169. */
  170. function me() {
  171. global $ME;
  172. return $ME;
  173. }
  174. /**
  175. * Guesses the full URL of the current script.
  176. *
  177. * This function is using $PAGE->url, but may fall back to $FULLME which
  178. * is constructed from PHP_SELF and REQUEST_URI or SCRIPT_NAME
  179. *
  180. * @return mixed full page URL string or false if unknown
  181. */
  182. function qualified_me() {
  183. global $FULLME, $PAGE, $CFG;
  184. if (isset($PAGE) and $PAGE->has_set_url()) {
  185. // this is the only recommended way to find out current page
  186. return $PAGE->url->out(false);
  187. } else {
  188. if ($FULLME === null) {
  189. // CLI script most probably
  190. return false;
  191. }
  192. if (!empty($CFG->sslproxy)) {
  193. // return only https links when using SSL proxy
  194. return preg_replace('/^http:/', 'https:', $FULLME, 1);
  195. } else {
  196. return $FULLME;
  197. }
  198. }
  199. }
  200. /**
  201. * Class for creating and manipulating urls.
  202. *
  203. * It can be used in moodle pages where config.php has been included without any further includes.
  204. *
  205. * It is useful for manipulating urls with long lists of params.
  206. * One situation where it will be useful is a page which links to itself to perform various actions
  207. * and / or to process form data. A moodle_url object :
  208. * can be created for a page to refer to itself with all the proper get params being passed from page call to
  209. * page call and methods can be used to output a url including all the params, optionally adding and overriding
  210. * params and can also be used to
  211. * - output the url without any get params
  212. * - and output the params as hidden fields to be output within a form
  213. *
  214. * @link http://docs.moodle.org/dev/lib/weblib.php_moodle_url See short write up here
  215. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  216. * @package moodlecore
  217. */
  218. class moodle_url {
  219. /**
  220. * Scheme, ex.: http, https
  221. * @var string
  222. */
  223. protected $scheme = '';
  224. /**
  225. * hostname
  226. * @var string
  227. */
  228. protected $host = '';
  229. /**
  230. * Port number, empty means default 80 or 443 in case of http
  231. * @var unknown_type
  232. */
  233. protected $port = '';
  234. /**
  235. * Username for http auth
  236. * @var string
  237. */
  238. protected $user = '';
  239. /**
  240. * Password for http auth
  241. * @var string
  242. */
  243. protected $pass = '';
  244. /**
  245. * Script path
  246. * @var string
  247. */
  248. protected $path = '';
  249. /**
  250. * Optional slash argument value
  251. * @var string
  252. */
  253. protected $slashargument = '';
  254. /**
  255. * Anchor, may be also empty, null means none
  256. * @var string
  257. */
  258. protected $anchor = null;
  259. /**
  260. * Url parameters as associative array
  261. * @var array
  262. */
  263. protected $params = array(); // Associative array of query string params
  264. /**
  265. * Create new instance of moodle_url.
  266. *
  267. * @param moodle_url|string $url - moodle_url means make a copy of another
  268. * moodle_url and change parameters, string means full url or shortened
  269. * form (ex.: '/course/view.php'). It is strongly encouraged to not include
  270. * query string because it may result in double encoded values. Use the
  271. * $params instead. For admin URLs, just use /admin/script.php, this
  272. * class takes care of the $CFG->admin issue.
  273. * @param array $params these params override current params or add new
  274. */
  275. public function __construct($url, array $params = null) {
  276. global $CFG;
  277. if ($url instanceof moodle_url) {
  278. $this->scheme = $url->scheme;
  279. $this->host = $url->host;
  280. $this->port = $url->port;
  281. $this->user = $url->user;
  282. $this->pass = $url->pass;
  283. $this->path = $url->path;
  284. $this->slashargument = $url->slashargument;
  285. $this->params = $url->params;
  286. $this->anchor = $url->anchor;
  287. } else {
  288. // detect if anchor used
  289. $apos = strpos($url, '#');
  290. if ($apos !== false) {
  291. $anchor = substr($url, $apos);
  292. $anchor = ltrim($anchor, '#');
  293. $this->set_anchor($anchor);
  294. $url = substr($url, 0, $apos);
  295. }
  296. // normalise shortened form of our url ex.: '/course/view.php'
  297. if (strpos($url, '/') === 0) {
  298. // we must not use httpswwwroot here, because it might be url of other page,
  299. // devs have to use httpswwwroot explicitly when creating new moodle_url
  300. $url = $CFG->wwwroot.$url;
  301. }
  302. // now fix the admin links if needed, no need to mess with httpswwwroot
  303. if ($CFG->admin !== 'admin') {
  304. if (strpos($url, "$CFG->wwwroot/admin/") === 0) {
  305. $url = str_replace("$CFG->wwwroot/admin/", "$CFG->wwwroot/$CFG->admin/", $url);
  306. }
  307. }
  308. // parse the $url
  309. $parts = parse_url($url);
  310. if ($parts === false) {
  311. throw new moodle_exception('invalidurl');
  312. }
  313. if (isset($parts['query'])) {
  314. // note: the values may not be correctly decoded,
  315. // url parameters should be always passed as array
  316. parse_str(str_replace('&amp;', '&', $parts['query']), $this->params);
  317. }
  318. unset($parts['query']);
  319. foreach ($parts as $key => $value) {
  320. $this->$key = $value;
  321. }
  322. // detect slashargument value from path - we do not support directory names ending with .php
  323. $pos = strpos($this->path, '.php/');
  324. if ($pos !== false) {
  325. $this->slashargument = substr($this->path, $pos + 4);
  326. $this->path = substr($this->path, 0, $pos + 4);
  327. }
  328. }
  329. $this->params($params);
  330. }
  331. /**
  332. * Add an array of params to the params for this url.
  333. *
  334. * The added params override existing ones if they have the same name.
  335. *
  336. * @param array $params Defaults to null. If null then returns all params.
  337. * @return array Array of Params for url.
  338. */
  339. public function params(array $params = null) {
  340. $params = (array)$params;
  341. foreach ($params as $key=>$value) {
  342. if (is_int($key)) {
  343. throw new coding_exception('Url parameters can not have numeric keys!');
  344. }
  345. if (!is_string($value)) {
  346. if (is_array($value)) {
  347. throw new coding_exception('Url parameters values can not be arrays!');
  348. }
  349. if (is_object($value) and !method_exists($value, '__toString')) {
  350. throw new coding_exception('Url parameters values can not be objects, unless __toString() is defined!');
  351. }
  352. }
  353. $this->params[$key] = (string)$value;
  354. }
  355. return $this->params;
  356. }
  357. /**
  358. * Remove all params if no arguments passed.
  359. * Remove selected params if arguments are passed.
  360. *
  361. * Can be called as either remove_params('param1', 'param2')
  362. * or remove_params(array('param1', 'param2')).
  363. *
  364. * @param mixed $params either an array of param names, or a string param name,
  365. * @param string $params,... any number of additional param names.
  366. * @return array url parameters
  367. */
  368. public function remove_params($params = null) {
  369. if (!is_array($params)) {
  370. $params = func_get_args();
  371. }
  372. foreach ($params as $param) {
  373. unset($this->params[$param]);
  374. }
  375. return $this->params;
  376. }
  377. /**
  378. * Remove all url parameters
  379. * @param $params
  380. * @return void
  381. */
  382. public function remove_all_params($params = null) {
  383. $this->params = array();
  384. $this->slashargument = '';
  385. }
  386. /**
  387. * Add a param to the params for this url.
  388. *
  389. * The added param overrides existing one if they have the same name.
  390. *
  391. * @param string $paramname name
  392. * @param string $newvalue Param value. If new value specified current value is overriden or parameter is added
  393. * @return mixed string parameter value, null if parameter does not exist
  394. */
  395. public function param($paramname, $newvalue = '') {
  396. if (func_num_args() > 1) {
  397. // set new value
  398. $this->params(array($paramname=>$newvalue));
  399. }
  400. if (isset($this->params[$paramname])) {
  401. return $this->params[$paramname];
  402. } else {
  403. return null;
  404. }
  405. }
  406. /**
  407. * Merges parameters and validates them
  408. * @param array $overrideparams
  409. * @return array merged parameters
  410. */
  411. protected function merge_overrideparams(array $overrideparams = null) {
  412. $overrideparams = (array)$overrideparams;
  413. $params = $this->params;
  414. foreach ($overrideparams as $key=>$value) {
  415. if (is_int($key)) {
  416. throw new coding_exception('Overridden parameters can not have numeric keys!');
  417. }
  418. if (is_array($value)) {
  419. throw new coding_exception('Overridden parameters values can not be arrays!');
  420. }
  421. if (is_object($value) and !method_exists($value, '__toString')) {
  422. throw new coding_exception('Overridden parameters values can not be objects, unless __toString() is defined!');
  423. }
  424. $params[$key] = (string)$value;
  425. }
  426. return $params;
  427. }
  428. /**
  429. * Get the params as as a query string.
  430. * This method should not be used outside of this method.
  431. *
  432. * @param boolean $escaped Use &amp; as params separator instead of plain &
  433. * @param array $overrideparams params to add to the output params, these
  434. * override existing ones with the same name.
  435. * @return string query string that can be added to a url.
  436. */
  437. public function get_query_string($escaped = true, array $overrideparams = null) {
  438. $arr = array();
  439. if ($overrideparams !== null) {
  440. $params = $this->merge_overrideparams($overrideparams);
  441. } else {
  442. $params = $this->params;
  443. }
  444. foreach ($params as $key => $val) {
  445. if (is_array($val)) {
  446. foreach ($val as $index => $value) {
  447. $arr[] = rawurlencode($key.'['.$index.']')."=".rawurlencode($value);
  448. }
  449. } else {
  450. $arr[] = rawurlencode($key)."=".rawurlencode($val);
  451. }
  452. }
  453. if ($escaped) {
  454. return implode('&amp;', $arr);
  455. } else {
  456. return implode('&', $arr);
  457. }
  458. }
  459. /**
  460. * Shortcut for printing of encoded URL.
  461. * @return string
  462. */
  463. public function __toString() {
  464. return $this->out(true);
  465. }
  466. /**
  467. * Output url
  468. *
  469. * If you use the returned URL in HTML code, you want the escaped ampersands. If you use
  470. * the returned URL in HTTP headers, you want $escaped=false.
  471. *
  472. * @param boolean $escaped Use &amp; as params separator instead of plain &
  473. * @param array $overrideparams params to add to the output url, these override existing ones with the same name.
  474. * @return string Resulting URL
  475. */
  476. public function out($escaped = true, array $overrideparams = null) {
  477. if (!is_bool($escaped)) {
  478. debugging('Escape parameter must be of type boolean, '.gettype($escaped).' given instead.');
  479. }
  480. $uri = $this->out_omit_querystring().$this->slashargument;
  481. $querystring = $this->get_query_string($escaped, $overrideparams);
  482. if ($querystring !== '') {
  483. $uri .= '?' . $querystring;
  484. }
  485. if (!is_null($this->anchor)) {
  486. $uri .= '#'.$this->anchor;
  487. }
  488. return $uri;
  489. }
  490. /**
  491. * Returns url without parameters, everything before '?'.
  492. *
  493. * @param bool $includeanchor if {@link self::anchor} is defined, should it be returned?
  494. * @return string
  495. */
  496. public function out_omit_querystring($includeanchor = false) {
  497. $uri = $this->scheme ? $this->scheme.':'.((strtolower($this->scheme) == 'mailto') ? '':'//'): '';
  498. $uri .= $this->user ? $this->user.($this->pass? ':'.$this->pass:'').'@':'';
  499. $uri .= $this->host ? $this->host : '';
  500. $uri .= $this->port ? ':'.$this->port : '';
  501. $uri .= $this->path ? $this->path : '';
  502. if ($includeanchor and !is_null($this->anchor)) {
  503. $uri .= '#' . $this->anchor;
  504. }
  505. return $uri;
  506. }
  507. /**
  508. * Compares this moodle_url with another
  509. * See documentation of constants for an explanation of the comparison flags.
  510. * @param moodle_url $url The moodle_url object to compare
  511. * @param int $matchtype The type of comparison (URL_MATCH_BASE, URL_MATCH_PARAMS, URL_MATCH_EXACT)
  512. * @return boolean
  513. */
  514. public function compare(moodle_url $url, $matchtype = URL_MATCH_EXACT) {
  515. $baseself = $this->out_omit_querystring();
  516. $baseother = $url->out_omit_querystring();
  517. // Append index.php if there is no specific file
  518. if (substr($baseself,-1)=='/') {
  519. $baseself .= 'index.php';
  520. }
  521. if (substr($baseother,-1)=='/') {
  522. $baseother .= 'index.php';
  523. }
  524. // Compare the two base URLs
  525. if ($baseself != $baseother) {
  526. return false;
  527. }
  528. if ($matchtype == URL_MATCH_BASE) {
  529. return true;
  530. }
  531. $urlparams = $url->params();
  532. foreach ($this->params() as $param => $value) {
  533. if ($param == 'sesskey') {
  534. continue;
  535. }
  536. if (!array_key_exists($param, $urlparams) || $urlparams[$param] != $value) {
  537. return false;
  538. }
  539. }
  540. if ($matchtype == URL_MATCH_PARAMS) {
  541. return true;
  542. }
  543. foreach ($urlparams as $param => $value) {
  544. if ($param == 'sesskey') {
  545. continue;
  546. }
  547. if (!array_key_exists($param, $this->params()) || $this->param($param) != $value) {
  548. return false;
  549. }
  550. }
  551. return true;
  552. }
  553. /**
  554. * Sets the anchor for the URI (the bit after the hash)
  555. * @param string $anchor null means remove previous
  556. */
  557. public function set_anchor($anchor) {
  558. if (is_null($anchor)) {
  559. // remove
  560. $this->anchor = null;
  561. } else if ($anchor === '') {
  562. // special case, used as empty link
  563. $this->anchor = '';
  564. } else if (preg_match('|[a-zA-Z\_\:][a-zA-Z0-9\_\-\.\:]*|', $anchor)) {
  565. // Match the anchor against the NMTOKEN spec
  566. $this->anchor = $anchor;
  567. } else {
  568. // bad luck, no valid anchor found
  569. $this->anchor = null;
  570. }
  571. }
  572. /**
  573. * Sets the url slashargument value
  574. * @param string $path usually file path
  575. * @param string $parameter name of page parameter if slasharguments not supported
  576. * @param bool $supported usually null, then it depends on $CFG->slasharguments, use true or false for other servers
  577. * @return void
  578. */
  579. public function set_slashargument($path, $parameter = 'file', $supported = NULL) {
  580. global $CFG;
  581. if (is_null($supported)) {
  582. $supported = $CFG->slasharguments;
  583. }
  584. if ($supported) {
  585. $parts = explode('/', $path);
  586. $parts = array_map('rawurlencode', $parts);
  587. $path = implode('/', $parts);
  588. $this->slashargument = $path;
  589. unset($this->params[$parameter]);
  590. } else {
  591. $this->slashargument = '';
  592. $this->params[$parameter] = $path;
  593. }
  594. }
  595. // == static factory methods ==
  596. /**
  597. * General moodle file url.
  598. * @param string $urlbase the script serving the file
  599. * @param string $path
  600. * @param bool $forcedownload
  601. * @return moodle_url
  602. */
  603. public static function make_file_url($urlbase, $path, $forcedownload = false) {
  604. global $CFG;
  605. $params = array();
  606. if ($forcedownload) {
  607. $params['forcedownload'] = 1;
  608. }
  609. $url = new moodle_url($urlbase, $params);
  610. $url->set_slashargument($path);
  611. return $url;
  612. }
  613. /**
  614. * Factory method for creation of url pointing to plugin file.
  615. * Please note this method can be used only from the plugins to
  616. * create urls of own files, it must not be used outside of plugins!
  617. * @param int $contextid
  618. * @param string $component
  619. * @param string $area
  620. * @param int $itemid
  621. * @param string $pathname
  622. * @param string $filename
  623. * @param bool $forcedownload
  624. * @return moodle_url
  625. */
  626. public static function make_pluginfile_url($contextid, $component, $area, $itemid, $pathname, $filename, $forcedownload = false) {
  627. global $CFG;
  628. $urlbase = "$CFG->httpswwwroot/pluginfile.php";
  629. if ($itemid === NULL) {
  630. return self::make_file_url($urlbase, "/$contextid/$component/$area".$pathname.$filename, $forcedownload);
  631. } else {
  632. return self::make_file_url($urlbase, "/$contextid/$component/$area/$itemid".$pathname.$filename, $forcedownload);
  633. }
  634. }
  635. /**
  636. * Factory method for creation of url pointing to draft
  637. * file of current user.
  638. * @param int $draftid draft item id
  639. * @param string $pathname
  640. * @param string $filename
  641. * @param bool $forcedownload
  642. * @return moodle_url
  643. */
  644. public static function make_draftfile_url($draftid, $pathname, $filename, $forcedownload = false) {
  645. global $CFG, $USER;
  646. $urlbase = "$CFG->httpswwwroot/draftfile.php";
  647. $context = context_user::instance($USER->id);
  648. return self::make_file_url($urlbase, "/$context->id/user/draft/$draftid".$pathname.$filename, $forcedownload);
  649. }
  650. /**
  651. * Factory method for creating of links to legacy
  652. * course files.
  653. * @param int $courseid
  654. * @param string $filepath
  655. * @param bool $forcedownload
  656. * @return moodle_url
  657. */
  658. public static function make_legacyfile_url($courseid, $filepath, $forcedownload = false) {
  659. global $CFG;
  660. $urlbase = "$CFG->wwwroot/file.php";
  661. return self::make_file_url($urlbase, '/'.$courseid.'/'.$filepath, $forcedownload);
  662. }
  663. /**
  664. * Returns URL a relative path from $CFG->wwwroot
  665. *
  666. * Can be used for passing around urls with the wwwroot stripped
  667. *
  668. * @param boolean $escaped Use &amp; as params separator instead of plain &
  669. * @param array $overrideparams params to add to the output url, these override existing ones with the same name.
  670. * @return string Resulting URL
  671. * @throws coding_exception if called on a non-local url
  672. */
  673. public function out_as_local_url($escaped = true, array $overrideparams = null) {
  674. global $CFG;
  675. $url = $this->out($escaped, $overrideparams);
  676. $httpswwwroot = str_replace("http://", "https://", $CFG->wwwroot);
  677. // $url should be equal to wwwroot or httpswwwroot. If not then throw exception.
  678. if (($url === $CFG->wwwroot) || (strpos($url, $CFG->wwwroot.'/') === 0)) {
  679. $localurl = substr($url, strlen($CFG->wwwroot));
  680. return !empty($localurl) ? $localurl : '';
  681. } else if (($url === $httpswwwroot) || (strpos($url, $httpswwwroot.'/') === 0)) {
  682. $localurl = substr($url, strlen($httpswwwroot));
  683. return !empty($localurl) ? $localurl : '';
  684. } else {
  685. throw new coding_exception('out_as_local_url called on a non-local URL');
  686. }
  687. }
  688. /**
  689. * Returns the 'path' portion of a URL. For example, if the URL is
  690. * http://www.example.org:447/my/file/is/here.txt?really=1 then this will
  691. * return '/my/file/is/here.txt'.
  692. *
  693. * By default the path includes slash-arguments (for example,
  694. * '/myfile.php/extra/arguments') so it is what you would expect from a
  695. * URL path. If you don't want this behaviour, you can opt to exclude the
  696. * slash arguments. (Be careful: if the $CFG variable slasharguments is
  697. * disabled, these URLs will have a different format and you may need to
  698. * look at the 'file' parameter too.)
  699. *
  700. * @param bool $includeslashargument If true, includes slash arguments
  701. * @return string Path of URL
  702. */
  703. public function get_path($includeslashargument = true) {
  704. return $this->path . ($includeslashargument ? $this->slashargument : '');
  705. }
  706. /**
  707. * Returns a given parameter value from the URL.
  708. *
  709. * @param string $name Name of parameter
  710. * @return string Value of parameter or null if not set
  711. */
  712. public function get_param($name) {
  713. if (array_key_exists($name, $this->params)) {
  714. return $this->params[$name];
  715. } else {
  716. return null;
  717. }
  718. }
  719. }
  720. /**
  721. * Determine if there is data waiting to be processed from a form
  722. *
  723. * Used on most forms in Moodle to check for data
  724. * Returns the data as an object, if it's found.
  725. * This object can be used in foreach loops without
  726. * casting because it's cast to (array) automatically
  727. *
  728. * Checks that submitted POST data exists and returns it as object.
  729. *
  730. * @uses $_POST
  731. * @return mixed false or object
  732. */
  733. function data_submitted() {
  734. if (empty($_POST)) {
  735. return false;
  736. } else {
  737. return (object)fix_utf8($_POST);
  738. }
  739. }
  740. /**
  741. * Given some normal text this function will break up any
  742. * long words to a given size by inserting the given character
  743. *
  744. * It's multibyte savvy and doesn't change anything inside html tags.
  745. *
  746. * @param string $string the string to be modified
  747. * @param int $maxsize maximum length of the string to be returned
  748. * @param string $cutchar the string used to represent word breaks
  749. * @return string
  750. */
  751. function break_up_long_words($string, $maxsize=20, $cutchar=' ') {
  752. /// First of all, save all the tags inside the text to skip them
  753. $tags = array();
  754. filter_save_tags($string,$tags);
  755. /// Process the string adding the cut when necessary
  756. $output = '';
  757. $length = textlib::strlen($string);
  758. $wordlength = 0;
  759. for ($i=0; $i<$length; $i++) {
  760. $char = textlib::substr($string, $i, 1);
  761. if ($char == ' ' or $char == "\t" or $char == "\n" or $char == "\r" or $char == "<" or $char == ">") {
  762. $wordlength = 0;
  763. } else {
  764. $wordlength++;
  765. if ($wordlength > $maxsize) {
  766. $output .= $cutchar;
  767. $wordlength = 0;
  768. }
  769. }
  770. $output .= $char;
  771. }
  772. /// Finally load the tags back again
  773. if (!empty($tags)) {
  774. $output = str_replace(array_keys($tags), $tags, $output);
  775. }
  776. return $output;
  777. }
  778. /**
  779. * Try and close the current window using JavaScript, either immediately, or after a delay.
  780. *
  781. * Echo's out the resulting XHTML & javascript
  782. *
  783. * @global object
  784. * @global object
  785. * @param integer $delay a delay in seconds before closing the window. Default 0.
  786. * @param boolean $reloadopener if true, we will see if this window was a pop-up, and try
  787. * to reload the parent window before this one closes.
  788. */
  789. function close_window($delay = 0, $reloadopener = false) {
  790. global $PAGE, $OUTPUT;
  791. if (!$PAGE->headerprinted) {
  792. $PAGE->set_title(get_string('closewindow'));
  793. echo $OUTPUT->header();
  794. } else {
  795. $OUTPUT->container_end_all(false);
  796. }
  797. if ($reloadopener) {
  798. // Trigger the reload immediately, even if the reload is after a delay.
  799. $PAGE->requires->js_function_call('window.opener.location.reload', array(true));
  800. }
  801. $OUTPUT->notification(get_string('windowclosing'), 'notifysuccess');
  802. $PAGE->requires->js_function_call('close_window', array(new stdClass()), false, $delay);
  803. echo $OUTPUT->footer();
  804. exit;
  805. }
  806. /**
  807. * Returns a string containing a link to the user documentation for the current
  808. * page. Also contains an icon by default. Shown to teachers and admin only.
  809. *
  810. * @global object
  811. * @global object
  812. * @param string $text The text to be displayed for the link
  813. * @param string $iconpath The path to the icon to be displayed
  814. * @return string The link to user documentation for this current page
  815. */
  816. function page_doc_link($text='') {
  817. global $CFG, $PAGE, $OUTPUT;
  818. if (empty($CFG->docroot) || during_initial_install()) {
  819. return '';
  820. }
  821. if (!has_capability('moodle/site:doclinks', $PAGE->context)) {
  822. return '';
  823. }
  824. $path = $PAGE->docspath;
  825. if (!$path) {
  826. return '';
  827. }
  828. return $OUTPUT->doc_link($path, $text);
  829. }
  830. /**
  831. * Validates an email to make sure it makes sense.
  832. *
  833. * @param string $address The email address to validate.
  834. * @return boolean
  835. */
  836. function validate_email($address) {
  837. return (preg_match('#^[-!\#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+'.
  838. '(\.[-!\#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+)*'.
  839. '@'.
  840. '[-!\#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.
  841. '[-!\#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$#',
  842. $address));
  843. }
  844. /**
  845. * Extracts file argument either from file parameter or PATH_INFO
  846. * Note: $scriptname parameter is not needed anymore
  847. *
  848. * @global string
  849. * @uses $_SERVER
  850. * @uses PARAM_PATH
  851. * @return string file path (only safe characters)
  852. */
  853. function get_file_argument() {
  854. global $SCRIPT;
  855. $relativepath = optional_param('file', FALSE, PARAM_PATH);
  856. if ($relativepath !== false and $relativepath !== '') {
  857. return $relativepath;
  858. }
  859. $relativepath = false;
  860. // then try extract file from the slasharguments
  861. if (stripos($_SERVER['SERVER_SOFTWARE'], 'iis') !== false) {
  862. // NOTE: ISS tends to convert all file paths to single byte DOS encoding,
  863. // we can not use other methods because they break unicode chars,
  864. // the only way is to use URL rewriting
  865. if (isset($_SERVER['PATH_INFO']) and $_SERVER['PATH_INFO'] !== '') {
  866. // check that PATH_INFO works == must not contain the script name
  867. if (strpos($_SERVER['PATH_INFO'], $SCRIPT) === false) {
  868. $relativepath = clean_param(urldecode($_SERVER['PATH_INFO']), PARAM_PATH);
  869. }
  870. }
  871. } else {
  872. // all other apache-like servers depend on PATH_INFO
  873. if (isset($_SERVER['PATH_INFO'])) {
  874. if (isset($_SERVER['SCRIPT_NAME']) and strpos($_SERVER['PATH_INFO'], $_SERVER['SCRIPT_NAME']) === 0) {
  875. $relativepath = substr($_SERVER['PATH_INFO'], strlen($_SERVER['SCRIPT_NAME']));
  876. } else {
  877. $relativepath = $_SERVER['PATH_INFO'];
  878. }
  879. $relativepath = clean_param($relativepath, PARAM_PATH);
  880. }
  881. }
  882. return $relativepath;
  883. }
  884. /**
  885. * Just returns an array of text formats suitable for a popup menu
  886. *
  887. * @uses FORMAT_MOODLE
  888. * @uses FORMAT_HTML
  889. * @uses FORMAT_PLAIN
  890. * @uses FORMAT_MARKDOWN
  891. * @return array
  892. */
  893. function format_text_menu() {
  894. return array (FORMAT_MOODLE => get_string('formattext'),
  895. FORMAT_HTML => get_string('formathtml'),
  896. FORMAT_PLAIN => get_string('formatplain'),
  897. FORMAT_MARKDOWN => get_string('formatmarkdown'));
  898. }
  899. /**
  900. * Given text in a variety of format codings, this function returns
  901. * the text as safe HTML.
  902. *
  903. * This function should mainly be used for long strings like posts,
  904. * answers, glossary items etc. For short strings @see format_string().
  905. *
  906. * <pre>
  907. * Options:
  908. * trusted : If true the string won't be cleaned. Default false required noclean=true.
  909. * noclean : If true the string won't be cleaned. Default false required trusted=true.
  910. * nocache : If true the strign will not be cached and will be formatted every call. Default false.
  911. * filter : If true the string will be run through applicable filters as well. Default true.
  912. * para : If true then the returned string will be wrapped in div tags. Default true.
  913. * newlines : If true then lines newline breaks will be converted to HTML newline breaks. Default true.
  914. * context : The context that will be used for filtering.
  915. * overflowdiv : If set to true the formatted text will be encased in a div
  916. * with the class no-overflow before being returned. Default false.
  917. * allowid : If true then id attributes will not be removed, even when
  918. * using htmlpurifier. Default false.
  919. * </pre>
  920. *
  921. * @todo Finish documenting this function
  922. *
  923. * @staticvar array $croncache
  924. * @param string $text The text to be formatted. This is raw text originally from user input.
  925. * @param int $format Identifier of the text format to be used
  926. * [FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_MARKDOWN]
  927. * @param object/array $options text formatting options
  928. * @param int $courseid_do_not_use deprecated course id, use context option instead
  929. * @return string
  930. */
  931. function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_do_not_use = NULL) {
  932. global $CFG, $COURSE, $DB, $PAGE;
  933. static $croncache = array();
  934. if ($text === '' || is_null($text)) {
  935. return ''; // no need to do any filters and cleaning
  936. }
  937. $options = (array)$options; // detach object, we can not modify it
  938. if (!isset($options['trusted'])) {
  939. $options['trusted'] = false;
  940. }
  941. if (!isset($options['noclean'])) {
  942. if ($options['trusted'] and trusttext_active()) {
  943. // no cleaning if text trusted and noclean not specified
  944. $options['noclean'] = true;
  945. } else {
  946. $options['noclean'] = false;
  947. }
  948. }
  949. if (!isset($options['nocache'])) {
  950. $options['nocache'] = false;
  951. }
  952. if (!isset($options['filter'])) {
  953. $options['filter'] = true;
  954. }
  955. if (!isset($options['para'])) {
  956. $options['para'] = true;
  957. }
  958. if (!isset($options['newlines'])) {
  959. $options['newlines'] = true;
  960. }
  961. if (!isset($options['overflowdiv'])) {
  962. $options['overflowdiv'] = false;
  963. }
  964. // Calculate best context
  965. if (empty($CFG->version) or $CFG->version < 2010072800 or during_initial_install()) {
  966. // do not filter anything during installation or before upgrade completes
  967. $context = null;
  968. } else if (isset($options['context'])) { // first by explicit passed context option
  969. if (is_object($options['context'])) {
  970. $context = $options['context'];
  971. } else {
  972. $context = context::instance_by_id($options['context']);
  973. }
  974. } else if ($courseid_do_not_use) {
  975. // legacy courseid
  976. $context = context_course::instance($courseid_do_not_use);
  977. } else {
  978. // fallback to $PAGE->context this may be problematic in CLI and other non-standard pages :-(
  979. $context = $PAGE->context;
  980. }
  981. if (!$context) {
  982. // either install/upgrade or something has gone really wrong because context does not exist (yet?)
  983. $options['nocache'] = true;
  984. $options['filter'] = false;
  985. }
  986. if ($options['filter']) {
  987. $filtermanager = filter_manager::instance();
  988. $filtermanager->setup_page_for_filters($PAGE, $context); // Setup global stuff filters may have.
  989. } else {
  990. $filtermanager = new null_filter_manager();
  991. }
  992. if (!empty($CFG->cachetext) and empty($options['nocache'])) {
  993. $hashstr = $text.'-'.$filtermanager->text_filtering_hash($context).'-'.$context->id.'-'.current_language().'-'.
  994. (int)$format.(int)$options['trusted'].(int)$options['noclean'].
  995. (int)$options['para'].(int)$options['newlines'];
  996. $time = time() - $CFG->cachetext;
  997. $md5key = md5($hashstr);
  998. if (CLI_SCRIPT) {
  999. if (isset($croncache[$md5key])) {
  1000. return $croncache[$md5key];
  1001. }
  1002. }
  1003. if ($oldcacheitem = $DB->get_record('cache_text', array('md5key'=>$md5key), '*', IGNORE_MULTIPLE)) {
  1004. if ($oldcacheitem->timemodified >= $time) {
  1005. if (CLI_SCRIPT) {
  1006. if (count($croncache) > 150) {
  1007. reset($croncache);
  1008. $key = key($croncache);
  1009. unset($croncache[$key]);
  1010. }
  1011. $croncache[$md5key] = $oldcacheitem->formattedtext;
  1012. }
  1013. return $oldcacheitem->formattedtext;
  1014. }
  1015. }
  1016. }
  1017. switch ($format) {
  1018. case FORMAT_HTML:
  1019. if (!$options['noclean']) {
  1020. $text = clean_text($text, FORMAT_HTML, $options);
  1021. }
  1022. $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_HTML, 'noclean' => $options['noclean']));
  1023. break;
  1024. case FORMAT_PLAIN:
  1025. $text = s($text); // cleans dangerous JS
  1026. $text = rebuildnolinktag($text);
  1027. $text = str_replace(' ', '&nbsp; ', $text);
  1028. $text = nl2br($text);
  1029. break;
  1030. case FORMAT_WIKI:
  1031. // this format is deprecated
  1032. $text = '<p>NOTICE: Wiki-like formatting has been removed from Moodle. You should not be seeing
  1033. this message as all texts should have been converted to Markdown format instead.
  1034. Please post a bug report to http://moodle.org/bugs with information about where you
  1035. saw this message.</p>'.s($text);
  1036. break;
  1037. case FORMAT_MARKDOWN:
  1038. $text = markdown_to_html($text);
  1039. if (!$options['noclean']) {
  1040. $text = clean_text($text, FORMAT_HTML, $options);
  1041. }
  1042. $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_MARKDOWN, 'noclean' => $options['noclean']));
  1043. break;
  1044. default: // FORMAT_MOODLE or anything else
  1045. $text = text_to_html($text, null, $options['para'], $options['newlines']);
  1046. if (!$options['noclean']) {
  1047. $text = clean_text($text, FORMAT_HTML, $options);
  1048. }
  1049. $text = $filtermanager->filter_text($text, $context, array('originalformat' => $format, 'noclean' => $options['noclean']));
  1050. break;
  1051. }
  1052. if ($options['filter']) {
  1053. // at this point there should not be any draftfile links any more,
  1054. // this happens when developers forget to post process the text.
  1055. // The only potential problem is that somebody might try to format
  1056. // the text before storing into database which would be itself big bug.
  1057. $text = str_replace("\"$CFG->httpswwwroot/draftfile.php", "\"$CFG->httpswwwroot/brokenfile.php#", $text);
  1058. }
  1059. // Warn people that we have removed this old mechanism, just in case they
  1060. // were stupid enough to rely on it.
  1061. if (isset($CFG->currenttextiscacheable)) {
  1062. debugging('Once upon a time, Moodle had a truly evil use of global variables ' .
  1063. 'called $CFG->currenttextiscacheable. The good news is that this no ' .
  1064. 'longer exists. The bad news is that you seem to be using a filter that '.
  1065. 'relies on it. Please seek out and destroy that filter code.', DEBUG_DEVELOPER);
  1066. }
  1067. if (!empty($options['overflowdiv'])) {
  1068. $text = html_writer::tag('div', $text, array('class'=>'no-overflow'));
  1069. }
  1070. if (empty($options['nocache']) and !empty($CFG->cachetext)) {
  1071. if (CLI_SCRIPT) {
  1072. // special static cron cache - no need to store it in db if its not already there
  1073. if (count($croncache) > 150) {
  1074. reset($croncache);
  1075. $key = key($croncache);
  1076. unset($croncache[$key]);
  1077. }
  1078. $croncache[$md5key] = $text;
  1079. return $text;
  1080. }
  1081. $newcacheitem = new stdClass();
  1082. $newcacheitem->md5key = $md5key;
  1083. $newcacheitem->formattedtext = $text;
  1084. $newcacheitem->timemodified = time();
  1085. if ($oldcacheitem) { // See bug 4677 for discussion
  1086. $newcacheitem->id = $oldcacheitem->id;
  1087. try {
  1088. $DB->update_record('cache_text', $newcacheitem); // Update existing record in the cache table
  1089. } catch (dml_exception $e) {
  1090. // It's unlikely that the cron cache cleaner could have
  1091. // deleted this entry in the meantime, as it allows
  1092. // some extra time to cover these cases.
  1093. }
  1094. } else {
  1095. try {
  1096. $DB->insert_record('cache_text', $newcacheitem); // Insert a new record in the cache table
  1097. } catch (dml_exception $e) {
  1098. // Again, it's possible that another user has caused this
  1099. // record to be created already in the time that it took
  1100. // to traverse this function. That's OK too, as the
  1101. // call above handles duplicate entries, and eventually
  1102. // the cron cleaner will delete them.
  1103. }
  1104. }
  1105. }
  1106. return $text;
  1107. }
  1108. /**
  1109. * Resets all data related to filters, called during upgrade or when filter settings change.
  1110. *
  1111. * @param bool $phpunitreset true means called from our PHPUnit integration test reset
  1112. * @return void
  1113. */
  1114. function reset_text_filters_cache($phpunitreset = false) {
  1115. global $CFG, $DB;
  1116. if (!$phpunitreset) {
  1117. $DB->delete_records('cache_text');
  1118. }
  1119. $purifdir = $CFG->cachedir.'/htmlpurifier';
  1120. remove_dir($purifdir, true);
  1121. }
  1122. /**
  1123. * Given a simple string, this function returns the string
  1124. * processed by enabled string filters if $CFG->filterall is enabled
  1125. *
  1126. * This function should be used to print short strings (non html) that
  1127. * need filter processing e.g. activity titles, post subjects,
  1128. * glossary concepts.
  1129. *
  1130. * @staticvar bool $strcache
  1131. * @param string $string The string to be filtered. Should be plain text, expect
  1132. * possibly for multilang tags.
  1133. * @param boolean $striplinks To strip any link in the result text.
  1134. Moodle 1.8 default changed from false to true! MDL-8713
  1135. * @param array $options options array/object or courseid
  1136. * @return string
  1137. */
  1138. function format_string($string, $striplinks = true, $options = NULL) {
  1139. global $CFG, $COURSE, $PAGE;
  1140. //We'll use a in-memory cache here to speed up repeated strings
  1141. static $strcache = false;
  1142. if (empty($CFG->version) or $CFG->version < 2010072800 or during_initial_install()) {
  1143. // do not filter anything during installation or before upgrade completes
  1144. return $string = strip_tags($string);
  1145. }
  1146. if ($strcache === false or count($strcache) > 2000) { // this number might need some tuning to limit memory usage in cron
  1147. $strcache = array();
  1148. }
  1149. if (is_numeric($options)) {
  1150. // legacy courseid usage
  1151. $options = array('context'=>context_course::instance($options));
  1152. } else {
  1153. $options = (array)$options; // detach object, we can not modify it
  1154. }
  1155. if (empty($options['context'])) {
  1156. // fallback to $PAGE->context this may be problematic in CLI and other non-standard pages :-(
  1157. $options['context'] = $PAGE->context;
  1158. } else if (is_numeric($options['context'])) {
  1159. $options['context'] = context::instance_by_id($options['context']);
  1160. }
  1161. if (!$options['context']) {
  1162. // we did not find any context? weird
  1163. return $string = strip_tags($string);
  1164. }
  1165. //Calculate md5
  1166. $md5 = md5($string.'<+>'.$striplinks.'<+>'.$options['context']->id.'<+>'.current_language());
  1167. //Fetch from cache if possible
  1168. if (isset($strcache[$md5])) {
  1169. return $strcache[$md5];
  1170. }
  1171. // First replace all ampersands not followed by html entity code
  1172. // Regular expression moved to its own method for easier unit testing
  1173. $string = replace_ampersands_not_followed_by_entity($string);
  1174. if (!empty($CFG->filterall)) {
  1175. $filtermanager = filter_manager::instance();
  1176. $filtermanager->setup_page_for_filters($PAGE, $options['context']); // Setup global stuff filters may have.
  1177. $string = $filtermanager->filter_string($string, $options['context']);
  1178. }
  1179. // If the site requires it, strip ALL tags from this string
  1180. if (!empty($CFG->formatstringstriptags)) {
  1181. $string = str_replace(array('<', '>'), array('&lt;', '&gt;'), strip_tags($string));
  1182. } else {
  1183. // Otherwise strip just links if that is required (default)
  1184. if ($striplinks) { //strip links in string
  1185. $string = strip_links($string);
  1186. }
  1187. $string = clean_text($string);
  1188. }
  1189. //Store to cache
  1190. $strcache[$md5] = $string;
  1191. return $string;
  1192. }
  1193. /**
  1194. * Given a string, performs a negative lookahead looking for any ampersand character
  1195. * that is not followed by a proper HTML entity. If any is found, it is replaced
  1196. * by &amp;. The string is then returned.
  1197. *
  1198. * @param string $string
  1199. * @return string
  1200. */
  1201. function replace_ampersands_not_followed_by_entity($string) {
  1202. return preg_replace("/\&(?![a-zA-Z0-9#]{1,8};)/", "&amp;", $string);
  1203. }
  1204. /**
  1205. * Given a string, replaces all <a>.*</a> by .* and returns the string.
  1206. *
  1207. * @param string $string
  1208. * @return string
  1209. */
  1210. function strip_links($string) {
  1211. return preg_replace('/(<a\s[^>]+?>)(.+?)(<\/a>)/is','$2',$string);
  1212. }
  1213. /**
  1214. * This expression turns links into something nice in a text format. (Russell Jungwirth)
  1215. *
  1216. * @param string $string
  1217. * @return string
  1218. */
  1219. function wikify_links($string) {
  1220. return preg_replace('~(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)~i','$3 [ $2 ]', $string);
  1221. }
  1222. /**
  1223. * Given text in a variety of format codings, this function returns
  1224. * the text as plain text suitable for plain email.
  1225. *
  1226. * @uses FORMAT_MOODLE
  1227. * @uses FORMAT_HTML
  1228. * @uses FORMAT_PLAIN
  1229. * @uses FORMAT_WIKI
  1230. * @uses FORMAT_MARKDOWN
  1231. * @param string $text The text to be formatted. This is raw text originally from user input.
  1232. * @param int $format Identifier of the text format to be used
  1233. * [FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN]
  1234. * @return string
  1235. */
  1236. function format_text_email($text, $format) {
  1237. switch ($format) {
  1238. case FORMAT_PLAIN:
  1239. return $text;
  1240. break;
  1241. case FORMAT_WIKI:
  1242. // there should not be any of these any more!
  1243. $text = wikify_links($text);
  1244. return textlib::entities_to_utf8(strip_tags($text), true);
  1245. break;
  1246. case FORMAT_HTML:
  1247. return html_to_text($text);
  1248. break;
  1249. case FORMAT_MOODLE:
  1250. case FORMAT_MARKDOWN:
  1251. default:
  1252. $text = wikify_links($text);
  1253. return textlib::entities_to_utf8(strip_tags($text), true);
  1254. break;
  1255. }
  1256. }
  1257. /**
  1258. * Formats activity intro text
  1259. *
  1260. * @global object
  1261. * @uses CONTEXT_MODULE
  1262. * @param string $module name of module
  1263. * @param object $activity instance of activity
  1264. * @param int $cmid course module id
  1265. * @param bool $filter filter resulting html text
  1266. * @return text
  1267. */
  1268. function format_module_intro($module, $activity, $cmid, $filter=true) {
  1269. global $CFG;
  1270. require_once("$CFG->libdir/filelib.php");
  1271. $context = context_module::instance($cmid);
  1272. $options = array('noclean'=>true, 'para'=>false, 'filter'=>$filter, 'context'=>$context, 'overflowdiv'=>true);
  1273. $intro = file_rewrite_pluginfile_urls($activity->intro, 'pluginfile.php', $context->id, 'mod_'.$module, 'intro', null);
  1274. return trim(format_text($intro, $activity->introformat, $options, null));
  1275. }
  1276. /**
  1277. * Legacy function, used for cleaning of old forum and glossary text only.
  1278. *
  1279. * @global object
  1280. * @param string $text text that may contain legacy TRUSTTEXT marker
  1281. * @return text without legacy TRUSTTEXT marker
  1282. */
  1283. function trusttext_strip($text) {
  1284. while (true) { //removing nested T