PageRenderTime 69ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 2ms

/lib/moodlelib.php

https://bitbucket.org/synergylearning/campusconnect
PHP | 9736 lines | 5500 code | 1191 blank | 3045 comment | 1334 complexity | 857d5a9c71af7fb935f408b6c4dc9501 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, LGPL-2.1, Apache-2.0, BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full 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. * moodlelib.php - Moodle main library
  18. *
  19. * Main library file of miscellaneous general-purpose Moodle functions.
  20. * Other main libraries:
  21. * - weblib.php - functions that produce web output
  22. * - datalib.php - functions that access the database
  23. *
  24. * @package core
  25. * @subpackage lib
  26. * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. */
  29. defined('MOODLE_INTERNAL') || die();
  30. // CONSTANTS (Encased in phpdoc proper comments).
  31. // Date and time constants.
  32. /**
  33. * Time constant - the number of seconds in a year
  34. */
  35. define('YEARSECS', 31536000);
  36. /**
  37. * Time constant - the number of seconds in a week
  38. */
  39. define('WEEKSECS', 604800);
  40. /**
  41. * Time constant - the number of seconds in a day
  42. */
  43. define('DAYSECS', 86400);
  44. /**
  45. * Time constant - the number of seconds in an hour
  46. */
  47. define('HOURSECS', 3600);
  48. /**
  49. * Time constant - the number of seconds in a minute
  50. */
  51. define('MINSECS', 60);
  52. /**
  53. * Time constant - the number of minutes in a day
  54. */
  55. define('DAYMINS', 1440);
  56. /**
  57. * Time constant - the number of minutes in an hour
  58. */
  59. define('HOURMINS', 60);
  60. // Parameter constants - every call to optional_param(), required_param()
  61. // or clean_param() should have a specified type of parameter.
  62. /**
  63. * PARAM_ALPHA - contains only english ascii letters a-zA-Z.
  64. */
  65. define('PARAM_ALPHA', 'alpha');
  66. /**
  67. * PARAM_ALPHAEXT the same contents as PARAM_ALPHA plus the chars in quotes: "_-" allowed
  68. * NOTE: originally this allowed "/" too, please use PARAM_SAFEPATH if "/" needed
  69. */
  70. define('PARAM_ALPHAEXT', 'alphaext');
  71. /**
  72. * PARAM_ALPHANUM - expected numbers and letters only.
  73. */
  74. define('PARAM_ALPHANUM', 'alphanum');
  75. /**
  76. * PARAM_ALPHANUMEXT - expected numbers, letters only and _-.
  77. */
  78. define('PARAM_ALPHANUMEXT', 'alphanumext');
  79. /**
  80. * PARAM_AUTH - actually checks to make sure the string is a valid auth plugin
  81. */
  82. define('PARAM_AUTH', 'auth');
  83. /**
  84. * PARAM_BASE64 - Base 64 encoded format
  85. */
  86. define('PARAM_BASE64', 'base64');
  87. /**
  88. * PARAM_BOOL - converts input into 0 or 1, use for switches in forms and urls.
  89. */
  90. define('PARAM_BOOL', 'bool');
  91. /**
  92. * PARAM_CAPABILITY - A capability name, like 'moodle/role:manage'. Actually
  93. * checked against the list of capabilities in the database.
  94. */
  95. define('PARAM_CAPABILITY', 'capability');
  96. /**
  97. * PARAM_CLEANHTML - cleans submitted HTML code. Note that you almost never want
  98. * to use this. The normal mode of operation is to use PARAM_RAW when recieving
  99. * the input (required/optional_param or formslib) and then sanitse the HTML
  100. * using format_text on output. This is for the rare cases when you want to
  101. * sanitise the HTML on input. This cleaning may also fix xhtml strictness.
  102. */
  103. define('PARAM_CLEANHTML', 'cleanhtml');
  104. /**
  105. * PARAM_EMAIL - an email address following the RFC
  106. */
  107. define('PARAM_EMAIL', 'email');
  108. /**
  109. * PARAM_FILE - safe file name, all dangerous chars are stripped, protects against XSS, SQL injections and directory traversals
  110. */
  111. define('PARAM_FILE', 'file');
  112. /**
  113. * PARAM_FLOAT - a real/floating point number.
  114. *
  115. * Note that you should not use PARAM_FLOAT for numbers typed in by the user.
  116. * It does not work for languages that use , as a decimal separator.
  117. * Instead, do something like
  118. * $rawvalue = required_param('name', PARAM_RAW);
  119. * // ... other code including require_login, which sets current lang ...
  120. * $realvalue = unformat_float($rawvalue);
  121. * // ... then use $realvalue
  122. */
  123. define('PARAM_FLOAT', 'float');
  124. /**
  125. * PARAM_HOST - expected fully qualified domain name (FQDN) or an IPv4 dotted quad (IP address)
  126. */
  127. define('PARAM_HOST', 'host');
  128. /**
  129. * PARAM_INT - integers only, use when expecting only numbers.
  130. */
  131. define('PARAM_INT', 'int');
  132. /**
  133. * PARAM_LANG - checks to see if the string is a valid installed language in the current site.
  134. */
  135. define('PARAM_LANG', 'lang');
  136. /**
  137. * PARAM_LOCALURL - expected properly formatted URL as well as one that refers to the local server itself. (NOT orthogonal to the
  138. * others! Implies PARAM_URL!)
  139. */
  140. define('PARAM_LOCALURL', 'localurl');
  141. /**
  142. * PARAM_NOTAGS - all html tags are stripped from the text. Do not abuse this type.
  143. */
  144. define('PARAM_NOTAGS', 'notags');
  145. /**
  146. * PARAM_PATH - safe relative path name, all dangerous chars are stripped, protects against XSS, SQL injections and directory
  147. * traversals note: the leading slash is not removed, window drive letter is not allowed
  148. */
  149. define('PARAM_PATH', 'path');
  150. /**
  151. * PARAM_PEM - Privacy Enhanced Mail format
  152. */
  153. define('PARAM_PEM', 'pem');
  154. /**
  155. * PARAM_PERMISSION - A permission, one of CAP_INHERIT, CAP_ALLOW, CAP_PREVENT or CAP_PROHIBIT.
  156. */
  157. define('PARAM_PERMISSION', 'permission');
  158. /**
  159. * PARAM_RAW specifies a parameter that is not cleaned/processed in any way except the discarding of the invalid utf-8 characters
  160. */
  161. define('PARAM_RAW', 'raw');
  162. /**
  163. * PARAM_RAW_TRIMMED like PARAM_RAW but leading and trailing whitespace is stripped.
  164. */
  165. define('PARAM_RAW_TRIMMED', 'raw_trimmed');
  166. /**
  167. * PARAM_SAFEDIR - safe directory name, suitable for include() and require()
  168. */
  169. define('PARAM_SAFEDIR', 'safedir');
  170. /**
  171. * PARAM_SAFEPATH - several PARAM_SAFEDIR joined by "/", suitable for include() and require(), plugin paths, etc.
  172. */
  173. define('PARAM_SAFEPATH', 'safepath');
  174. /**
  175. * PARAM_SEQUENCE - expects a sequence of numbers like 8 to 1,5,6,4,6,8,9. Numbers and comma only.
  176. */
  177. define('PARAM_SEQUENCE', 'sequence');
  178. /**
  179. * PARAM_TAG - one tag (interests, blogs, etc.) - mostly international characters and space, <> not supported
  180. */
  181. define('PARAM_TAG', 'tag');
  182. /**
  183. * PARAM_TAGLIST - list of tags separated by commas (interests, blogs, etc.)
  184. */
  185. define('PARAM_TAGLIST', 'taglist');
  186. /**
  187. * PARAM_TEXT - general plain text compatible with multilang filter, no other html tags. Please note '<', or '>' are allowed here.
  188. */
  189. define('PARAM_TEXT', 'text');
  190. /**
  191. * PARAM_THEME - Checks to see if the string is a valid theme name in the current site
  192. */
  193. define('PARAM_THEME', 'theme');
  194. /**
  195. * PARAM_URL - expected properly formatted URL. Please note that domain part is required, http://localhost/ is not accepted but
  196. * http://localhost.localdomain/ is ok.
  197. */
  198. define('PARAM_URL', 'url');
  199. /**
  200. * PARAM_USERNAME - Clean username to only contains allowed characters. This is to be used ONLY when manually creating user
  201. * accounts, do NOT use when syncing with external systems!!
  202. */
  203. define('PARAM_USERNAME', 'username');
  204. /**
  205. * PARAM_STRINGID - used to check if the given string is valid string identifier for get_string()
  206. */
  207. define('PARAM_STRINGID', 'stringid');
  208. // DEPRECATED PARAM TYPES OR ALIASES - DO NOT USE FOR NEW CODE.
  209. /**
  210. * PARAM_CLEAN - obsoleted, please use a more specific type of parameter.
  211. * It was one of the first types, that is why it is abused so much ;-)
  212. * @deprecated since 2.0
  213. */
  214. define('PARAM_CLEAN', 'clean');
  215. /**
  216. * PARAM_INTEGER - deprecated alias for PARAM_INT
  217. * @deprecated since 2.0
  218. */
  219. define('PARAM_INTEGER', 'int');
  220. /**
  221. * PARAM_NUMBER - deprecated alias of PARAM_FLOAT
  222. * @deprecated since 2.0
  223. */
  224. define('PARAM_NUMBER', 'float');
  225. /**
  226. * PARAM_ACTION - deprecated alias for PARAM_ALPHANUMEXT, use for various actions in forms and urls
  227. * NOTE: originally alias for PARAM_APLHA
  228. * @deprecated since 2.0
  229. */
  230. define('PARAM_ACTION', 'alphanumext');
  231. /**
  232. * PARAM_FORMAT - deprecated alias for PARAM_ALPHANUMEXT, use for names of plugins, formats, etc.
  233. * NOTE: originally alias for PARAM_APLHA
  234. * @deprecated since 2.0
  235. */
  236. define('PARAM_FORMAT', 'alphanumext');
  237. /**
  238. * PARAM_MULTILANG - deprecated alias of PARAM_TEXT.
  239. * @deprecated since 2.0
  240. */
  241. define('PARAM_MULTILANG', 'text');
  242. /**
  243. * PARAM_TIMEZONE - expected timezone. Timezone can be int +-(0-13) or float +-(0.5-12.5) or
  244. * string separated by '/' and can have '-' &/ '_' (eg. America/North_Dakota/New_Salem
  245. * America/Port-au-Prince)
  246. */
  247. define('PARAM_TIMEZONE', 'timezone');
  248. /**
  249. * PARAM_CLEANFILE - deprecated alias of PARAM_FILE; originally was removing regional chars too
  250. */
  251. define('PARAM_CLEANFILE', 'file');
  252. /**
  253. * PARAM_COMPONENT is used for full component names (aka frankenstyle) such as 'mod_forum', 'core_rating', 'auth_ldap'.
  254. * Short legacy subsystem names and module names are accepted too ex: 'forum', 'rating', 'user'.
  255. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  256. * NOTE: numbers and underscores are strongly discouraged in plugin names!
  257. */
  258. define('PARAM_COMPONENT', 'component');
  259. /**
  260. * PARAM_AREA is a name of area used when addressing files, comments, ratings, etc.
  261. * It is usually used together with context id and component.
  262. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  263. */
  264. define('PARAM_AREA', 'area');
  265. /**
  266. * PARAM_PLUGIN is used for plugin names such as 'forum', 'glossary', 'ldap', 'radius', 'paypal', 'completionstatus'.
  267. * Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
  268. * NOTE: numbers and underscores are strongly discouraged in plugin names! Underscores are forbidden in module names.
  269. */
  270. define('PARAM_PLUGIN', 'plugin');
  271. // Web Services.
  272. /**
  273. * VALUE_REQUIRED - if the parameter is not supplied, there is an error
  274. */
  275. define('VALUE_REQUIRED', 1);
  276. /**
  277. * VALUE_OPTIONAL - if the parameter is not supplied, then the param has no value
  278. */
  279. define('VALUE_OPTIONAL', 2);
  280. /**
  281. * VALUE_DEFAULT - if the parameter is not supplied, then the default value is used
  282. */
  283. define('VALUE_DEFAULT', 0);
  284. /**
  285. * NULL_NOT_ALLOWED - the parameter can not be set to null in the database
  286. */
  287. define('NULL_NOT_ALLOWED', false);
  288. /**
  289. * NULL_ALLOWED - the parameter can be set to null in the database
  290. */
  291. define('NULL_ALLOWED', true);
  292. // Page types.
  293. /**
  294. * PAGE_COURSE_VIEW is a definition of a page type. For more information on the page class see moodle/lib/pagelib.php.
  295. */
  296. define('PAGE_COURSE_VIEW', 'course-view');
  297. /** Get remote addr constant */
  298. define('GETREMOTEADDR_SKIP_HTTP_CLIENT_IP', '1');
  299. /** Get remote addr constant */
  300. define('GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR', '2');
  301. // Blog access level constant declaration.
  302. define ('BLOG_USER_LEVEL', 1);
  303. define ('BLOG_GROUP_LEVEL', 2);
  304. define ('BLOG_COURSE_LEVEL', 3);
  305. define ('BLOG_SITE_LEVEL', 4);
  306. define ('BLOG_GLOBAL_LEVEL', 5);
  307. // Tag constants.
  308. /**
  309. * To prevent problems with multibytes strings,Flag updating in nav not working on the review page. this should not exceed the
  310. * length of "varchar(255) / 3 (bytes / utf-8 character) = 85".
  311. * TODO: this is not correct, varchar(255) are 255 unicode chars ;-)
  312. *
  313. * @todo define(TAG_MAX_LENGTH) this is not correct, varchar(255) are 255 unicode chars ;-)
  314. */
  315. define('TAG_MAX_LENGTH', 50);
  316. // Password policy constants.
  317. define ('PASSWORD_LOWER', 'abcdefghijklmnopqrstuvwxyz');
  318. define ('PASSWORD_UPPER', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
  319. define ('PASSWORD_DIGITS', '0123456789');
  320. define ('PASSWORD_NONALPHANUM', '.,;:!?_-+/*@#&$');
  321. // Feature constants.
  322. // Used for plugin_supports() to report features that are, or are not, supported by a module.
  323. /** True if module can provide a grade */
  324. define('FEATURE_GRADE_HAS_GRADE', 'grade_has_grade');
  325. /** True if module supports outcomes */
  326. define('FEATURE_GRADE_OUTCOMES', 'outcomes');
  327. /** True if module supports advanced grading methods */
  328. define('FEATURE_ADVANCED_GRADING', 'grade_advanced_grading');
  329. /** True if module controls the grade visibility over the gradebook */
  330. define('FEATURE_CONTROLS_GRADE_VISIBILITY', 'controlsgradevisbility');
  331. /** True if module supports plagiarism plugins */
  332. define('FEATURE_PLAGIARISM', 'plagiarism');
  333. /** True if module has code to track whether somebody viewed it */
  334. define('FEATURE_COMPLETION_TRACKS_VIEWS', 'completion_tracks_views');
  335. /** True if module has custom completion rules */
  336. define('FEATURE_COMPLETION_HAS_RULES', 'completion_has_rules');
  337. /** True if module has no 'view' page (like label) */
  338. define('FEATURE_NO_VIEW_LINK', 'viewlink');
  339. /** True if module supports outcomes */
  340. define('FEATURE_IDNUMBER', 'idnumber');
  341. /** True if module supports groups */
  342. define('FEATURE_GROUPS', 'groups');
  343. /** True if module supports groupings */
  344. define('FEATURE_GROUPINGS', 'groupings');
  345. /** True if module supports groupmembersonly */
  346. define('FEATURE_GROUPMEMBERSONLY', 'groupmembersonly');
  347. /** Type of module */
  348. define('FEATURE_MOD_ARCHETYPE', 'mod_archetype');
  349. /** True if module supports intro editor */
  350. define('FEATURE_MOD_INTRO', 'mod_intro');
  351. /** True if module has default completion */
  352. define('FEATURE_MODEDIT_DEFAULT_COMPLETION', 'modedit_default_completion');
  353. define('FEATURE_COMMENT', 'comment');
  354. define('FEATURE_RATE', 'rate');
  355. /** True if module supports backup/restore of moodle2 format */
  356. define('FEATURE_BACKUP_MOODLE2', 'backup_moodle2');
  357. /** True if module can show description on course main page */
  358. define('FEATURE_SHOW_DESCRIPTION', 'showdescription');
  359. /** True if module uses the question bank */
  360. define('FEATURE_USES_QUESTIONS', 'usesquestions');
  361. /** Unspecified module archetype */
  362. define('MOD_ARCHETYPE_OTHER', 0);
  363. /** Resource-like type module */
  364. define('MOD_ARCHETYPE_RESOURCE', 1);
  365. /** Assignment module archetype */
  366. define('MOD_ARCHETYPE_ASSIGNMENT', 2);
  367. /** System (not user-addable) module archetype */
  368. define('MOD_ARCHETYPE_SYSTEM', 3);
  369. /** Return this from modname_get_types callback to use default display in activity chooser */
  370. define('MOD_SUBTYPE_NO_CHILDREN', 'modsubtypenochildren');
  371. /**
  372. * Security token used for allowing access
  373. * from external application such as web services.
  374. * Scripts do not use any session, performance is relatively
  375. * low because we need to load access info in each request.
  376. * Scripts are executed in parallel.
  377. */
  378. define('EXTERNAL_TOKEN_PERMANENT', 0);
  379. /**
  380. * Security token used for allowing access
  381. * of embedded applications, the code is executed in the
  382. * active user session. Token is invalidated after user logs out.
  383. * Scripts are executed serially - normal session locking is used.
  384. */
  385. define('EXTERNAL_TOKEN_EMBEDDED', 1);
  386. /**
  387. * The home page should be the site home
  388. */
  389. define('HOMEPAGE_SITE', 0);
  390. /**
  391. * The home page should be the users my page
  392. */
  393. define('HOMEPAGE_MY', 1);
  394. /**
  395. * The home page can be chosen by the user
  396. */
  397. define('HOMEPAGE_USER', 2);
  398. /**
  399. * Hub directory url (should be moodle.org)
  400. */
  401. define('HUB_HUBDIRECTORYURL', "http://hubdirectory.moodle.org");
  402. /**
  403. * Moodle.org url (should be moodle.org)
  404. */
  405. define('HUB_MOODLEORGHUBURL', "http://hub.moodle.org");
  406. /**
  407. * Moodle mobile app service name
  408. */
  409. define('MOODLE_OFFICIAL_MOBILE_SERVICE', 'moodle_mobile_app');
  410. /**
  411. * Indicates the user has the capabilities required to ignore activity and course file size restrictions
  412. */
  413. define('USER_CAN_IGNORE_FILE_SIZE_LIMITS', -1);
  414. /**
  415. * Course display settings: display all sections on one page.
  416. */
  417. define('COURSE_DISPLAY_SINGLEPAGE', 0);
  418. /**
  419. * Course display settings: split pages into a page per section.
  420. */
  421. define('COURSE_DISPLAY_MULTIPAGE', 1);
  422. /**
  423. * Authentication constant: String used in password field when password is not stored.
  424. */
  425. define('AUTH_PASSWORD_NOT_CACHED', 'not cached');
  426. // PARAMETER HANDLING.
  427. /**
  428. * Returns a particular value for the named variable, taken from
  429. * POST or GET. If the parameter doesn't exist then an error is
  430. * thrown because we require this variable.
  431. *
  432. * This function should be used to initialise all required values
  433. * in a script that are based on parameters. Usually it will be
  434. * used like this:
  435. * $id = required_param('id', PARAM_INT);
  436. *
  437. * Please note the $type parameter is now required and the value can not be array.
  438. *
  439. * @param string $parname the name of the page parameter we want
  440. * @param string $type expected type of parameter
  441. * @return mixed
  442. * @throws coding_exception
  443. */
  444. function required_param($parname, $type) {
  445. if (func_num_args() != 2 or empty($parname) or empty($type)) {
  446. throw new coding_exception('required_param() requires $parname and $type to be specified (parameter: '.$parname.')');
  447. }
  448. // POST has precedence.
  449. if (isset($_POST[$parname])) {
  450. $param = $_POST[$parname];
  451. } else if (isset($_GET[$parname])) {
  452. $param = $_GET[$parname];
  453. } else {
  454. print_error('missingparam', '', '', $parname);
  455. }
  456. if (is_array($param)) {
  457. debugging('Invalid array parameter detected in required_param(): '.$parname);
  458. // TODO: switch to fatal error in Moodle 2.3.
  459. return required_param_array($parname, $type);
  460. }
  461. return clean_param($param, $type);
  462. }
  463. /**
  464. * Returns a particular array value for the named variable, taken from
  465. * POST or GET. If the parameter doesn't exist then an error is
  466. * thrown because we require this variable.
  467. *
  468. * This function should be used to initialise all required values
  469. * in a script that are based on parameters. Usually it will be
  470. * used like this:
  471. * $ids = required_param_array('ids', PARAM_INT);
  472. *
  473. * Note: arrays of arrays are not supported, only alphanumeric keys with _ and - are supported
  474. *
  475. * @param string $parname the name of the page parameter we want
  476. * @param string $type expected type of parameter
  477. * @return array
  478. * @throws coding_exception
  479. */
  480. function required_param_array($parname, $type) {
  481. if (func_num_args() != 2 or empty($parname) or empty($type)) {
  482. throw new coding_exception('required_param_array() requires $parname and $type to be specified (parameter: '.$parname.')');
  483. }
  484. // POST has precedence.
  485. if (isset($_POST[$parname])) {
  486. $param = $_POST[$parname];
  487. } else if (isset($_GET[$parname])) {
  488. $param = $_GET[$parname];
  489. } else {
  490. print_error('missingparam', '', '', $parname);
  491. }
  492. if (!is_array($param)) {
  493. print_error('missingparam', '', '', $parname);
  494. }
  495. $result = array();
  496. foreach ($param as $key => $value) {
  497. if (!preg_match('/^[a-z0-9_-]+$/i', $key)) {
  498. debugging('Invalid key name in required_param_array() detected: '.$key.', parameter: '.$parname);
  499. continue;
  500. }
  501. $result[$key] = clean_param($value, $type);
  502. }
  503. return $result;
  504. }
  505. /**
  506. * Returns a particular value for the named variable, taken from
  507. * POST or GET, otherwise returning a given default.
  508. *
  509. * This function should be used to initialise all optional values
  510. * in a script that are based on parameters. Usually it will be
  511. * used like this:
  512. * $name = optional_param('name', 'Fred', PARAM_TEXT);
  513. *
  514. * Please note the $type parameter is now required and the value can not be array.
  515. *
  516. * @param string $parname the name of the page parameter we want
  517. * @param mixed $default the default value to return if nothing is found
  518. * @param string $type expected type of parameter
  519. * @return mixed
  520. * @throws coding_exception
  521. */
  522. function optional_param($parname, $default, $type) {
  523. if (func_num_args() != 3 or empty($parname) or empty($type)) {
  524. throw new coding_exception('optional_param requires $parname, $default + $type to be specified (parameter: '.$parname.')');
  525. }
  526. if (!isset($default)) {
  527. $default = null;
  528. }
  529. // POST has precedence.
  530. if (isset($_POST[$parname])) {
  531. $param = $_POST[$parname];
  532. } else if (isset($_GET[$parname])) {
  533. $param = $_GET[$parname];
  534. } else {
  535. return $default;
  536. }
  537. if (is_array($param)) {
  538. debugging('Invalid array parameter detected in required_param(): '.$parname);
  539. // TODO: switch to $default in Moodle 2.3.
  540. return optional_param_array($parname, $default, $type);
  541. }
  542. return clean_param($param, $type);
  543. }
  544. /**
  545. * Returns a particular array value for the named variable, taken from
  546. * POST or GET, otherwise returning a given default.
  547. *
  548. * This function should be used to initialise all optional values
  549. * in a script that are based on parameters. Usually it will be
  550. * used like this:
  551. * $ids = optional_param('id', array(), PARAM_INT);
  552. *
  553. * Note: arrays of arrays are not supported, only alphanumeric keys with _ and - are supported
  554. *
  555. * @param string $parname the name of the page parameter we want
  556. * @param mixed $default the default value to return if nothing is found
  557. * @param string $type expected type of parameter
  558. * @return array
  559. * @throws coding_exception
  560. */
  561. function optional_param_array($parname, $default, $type) {
  562. if (func_num_args() != 3 or empty($parname) or empty($type)) {
  563. throw new coding_exception('optional_param_array requires $parname, $default + $type to be specified (parameter: '.$parname.')');
  564. }
  565. // POST has precedence.
  566. if (isset($_POST[$parname])) {
  567. $param = $_POST[$parname];
  568. } else if (isset($_GET[$parname])) {
  569. $param = $_GET[$parname];
  570. } else {
  571. return $default;
  572. }
  573. if (!is_array($param)) {
  574. debugging('optional_param_array() expects array parameters only: '.$parname);
  575. return $default;
  576. }
  577. $result = array();
  578. foreach ($param as $key => $value) {
  579. if (!preg_match('/^[a-z0-9_-]+$/i', $key)) {
  580. debugging('Invalid key name in optional_param_array() detected: '.$key.', parameter: '.$parname);
  581. continue;
  582. }
  583. $result[$key] = clean_param($value, $type);
  584. }
  585. return $result;
  586. }
  587. /**
  588. * Strict validation of parameter values, the values are only converted
  589. * to requested PHP type. Internally it is using clean_param, the values
  590. * before and after cleaning must be equal - otherwise
  591. * an invalid_parameter_exception is thrown.
  592. * Objects and classes are not accepted.
  593. *
  594. * @param mixed $param
  595. * @param string $type PARAM_ constant
  596. * @param bool $allownull are nulls valid value?
  597. * @param string $debuginfo optional debug information
  598. * @return mixed the $param value converted to PHP type
  599. * @throws invalid_parameter_exception if $param is not of given type
  600. */
  601. function validate_param($param, $type, $allownull=NULL_NOT_ALLOWED, $debuginfo='') {
  602. if (is_null($param)) {
  603. if ($allownull == NULL_ALLOWED) {
  604. return null;
  605. } else {
  606. throw new invalid_parameter_exception($debuginfo);
  607. }
  608. }
  609. if (is_array($param) or is_object($param)) {
  610. throw new invalid_parameter_exception($debuginfo);
  611. }
  612. $cleaned = clean_param($param, $type);
  613. if ($type == PARAM_FLOAT) {
  614. // Do not detect precision loss here.
  615. if (is_float($param) or is_int($param)) {
  616. // These always fit.
  617. } else if (!is_numeric($param) or !preg_match('/^[\+-]?[0-9]*\.?[0-9]*(e[-+]?[0-9]+)?$/i', (string)$param)) {
  618. throw new invalid_parameter_exception($debuginfo);
  619. }
  620. } else if ((string)$param !== (string)$cleaned) {
  621. // Conversion to string is usually lossless.
  622. throw new invalid_parameter_exception($debuginfo);
  623. }
  624. return $cleaned;
  625. }
  626. /**
  627. * Makes sure array contains only the allowed types, this function does not validate array key names!
  628. *
  629. * <code>
  630. * $options = clean_param($options, PARAM_INT);
  631. * </code>
  632. *
  633. * @param array $param the variable array we are cleaning
  634. * @param string $type expected format of param after cleaning.
  635. * @param bool $recursive clean recursive arrays
  636. * @return array
  637. * @throws coding_exception
  638. */
  639. function clean_param_array(array $param = null, $type, $recursive = false) {
  640. // Convert null to empty array.
  641. $param = (array)$param;
  642. foreach ($param as $key => $value) {
  643. if (is_array($value)) {
  644. if ($recursive) {
  645. $param[$key] = clean_param_array($value, $type, true);
  646. } else {
  647. throw new coding_exception('clean_param_array can not process multidimensional arrays when $recursive is false.');
  648. }
  649. } else {
  650. $param[$key] = clean_param($value, $type);
  651. }
  652. }
  653. return $param;
  654. }
  655. /**
  656. * Used by {@link optional_param()} and {@link required_param()} to
  657. * clean the variables and/or cast to specific types, based on
  658. * an options field.
  659. * <code>
  660. * $course->format = clean_param($course->format, PARAM_ALPHA);
  661. * $selectedgradeitem = clean_param($selectedgradeitem, PARAM_INT);
  662. * </code>
  663. *
  664. * @param mixed $param the variable we are cleaning
  665. * @param string $type expected format of param after cleaning.
  666. * @return mixed
  667. * @throws coding_exception
  668. */
  669. function clean_param($param, $type) {
  670. global $CFG;
  671. if (is_array($param)) {
  672. throw new coding_exception('clean_param() can not process arrays, please use clean_param_array() instead.');
  673. } else if (is_object($param)) {
  674. if (method_exists($param, '__toString')) {
  675. $param = $param->__toString();
  676. } else {
  677. throw new coding_exception('clean_param() can not process objects, please use clean_param_array() instead.');
  678. }
  679. }
  680. switch ($type) {
  681. case PARAM_RAW:
  682. // No cleaning at all.
  683. $param = fix_utf8($param);
  684. return $param;
  685. case PARAM_RAW_TRIMMED:
  686. // No cleaning, but strip leading and trailing whitespace.
  687. $param = fix_utf8($param);
  688. return trim($param);
  689. case PARAM_CLEAN:
  690. // General HTML cleaning, try to use more specific type if possible this is deprecated!
  691. // Please use more specific type instead.
  692. if (is_numeric($param)) {
  693. return $param;
  694. }
  695. $param = fix_utf8($param);
  696. // Sweep for scripts, etc.
  697. return clean_text($param);
  698. case PARAM_CLEANHTML:
  699. // Clean html fragment.
  700. $param = fix_utf8($param);
  701. // Sweep for scripts, etc.
  702. $param = clean_text($param, FORMAT_HTML);
  703. return trim($param);
  704. case PARAM_INT:
  705. // Convert to integer.
  706. return (int)$param;
  707. case PARAM_FLOAT:
  708. // Convert to float.
  709. return (float)$param;
  710. case PARAM_ALPHA:
  711. // Remove everything not `a-z`.
  712. return preg_replace('/[^a-zA-Z]/i', '', $param);
  713. case PARAM_ALPHAEXT:
  714. // Remove everything not `a-zA-Z_-` (originally allowed "/" too).
  715. return preg_replace('/[^a-zA-Z_-]/i', '', $param);
  716. case PARAM_ALPHANUM:
  717. // Remove everything not `a-zA-Z0-9`.
  718. return preg_replace('/[^A-Za-z0-9]/i', '', $param);
  719. case PARAM_ALPHANUMEXT:
  720. // Remove everything not `a-zA-Z0-9_-`.
  721. return preg_replace('/[^A-Za-z0-9_-]/i', '', $param);
  722. case PARAM_SEQUENCE:
  723. // Remove everything not `0-9,`.
  724. return preg_replace('/[^0-9,]/i', '', $param);
  725. case PARAM_BOOL:
  726. // Convert to 1 or 0.
  727. $tempstr = strtolower($param);
  728. if ($tempstr === 'on' or $tempstr === 'yes' or $tempstr === 'true') {
  729. $param = 1;
  730. } else if ($tempstr === 'off' or $tempstr === 'no' or $tempstr === 'false') {
  731. $param = 0;
  732. } else {
  733. $param = empty($param) ? 0 : 1;
  734. }
  735. return $param;
  736. case PARAM_NOTAGS:
  737. // Strip all tags.
  738. $param = fix_utf8($param);
  739. return strip_tags($param);
  740. case PARAM_TEXT:
  741. // Leave only tags needed for multilang.
  742. $param = fix_utf8($param);
  743. // If the multilang syntax is not correct we strip all tags because it would break xhtml strict which is required
  744. // for accessibility standards please note this cleaning does not strip unbalanced '>' for BC compatibility reasons.
  745. do {
  746. if (strpos($param, '</lang>') !== false) {
  747. // Old and future mutilang syntax.
  748. $param = strip_tags($param, '<lang>');
  749. if (!preg_match_all('/<.*>/suU', $param, $matches)) {
  750. break;
  751. }
  752. $open = false;
  753. foreach ($matches[0] as $match) {
  754. if ($match === '</lang>') {
  755. if ($open) {
  756. $open = false;
  757. continue;
  758. } else {
  759. break 2;
  760. }
  761. }
  762. if (!preg_match('/^<lang lang="[a-zA-Z0-9_-]+"\s*>$/u', $match)) {
  763. break 2;
  764. } else {
  765. $open = true;
  766. }
  767. }
  768. if ($open) {
  769. break;
  770. }
  771. return $param;
  772. } else if (strpos($param, '</span>') !== false) {
  773. // Current problematic multilang syntax.
  774. $param = strip_tags($param, '<span>');
  775. if (!preg_match_all('/<.*>/suU', $param, $matches)) {
  776. break;
  777. }
  778. $open = false;
  779. foreach ($matches[0] as $match) {
  780. if ($match === '</span>') {
  781. if ($open) {
  782. $open = false;
  783. continue;
  784. } else {
  785. break 2;
  786. }
  787. }
  788. if (!preg_match('/^<span(\s+lang="[a-zA-Z0-9_-]+"|\s+class="multilang"){2}\s*>$/u', $match)) {
  789. break 2;
  790. } else {
  791. $open = true;
  792. }
  793. }
  794. if ($open) {
  795. break;
  796. }
  797. return $param;
  798. }
  799. } while (false);
  800. // Easy, just strip all tags, if we ever want to fix orphaned '&' we have to do that in format_string().
  801. return strip_tags($param);
  802. case PARAM_COMPONENT:
  803. // We do not want any guessing here, either the name is correct or not
  804. // please note only normalised component names are accepted.
  805. if (!preg_match('/^[a-z]+(_[a-z][a-z0-9_]*)?[a-z0-9]+$/', $param)) {
  806. return '';
  807. }
  808. if (strpos($param, '__') !== false) {
  809. return '';
  810. }
  811. if (strpos($param, 'mod_') === 0) {
  812. // Module names must not contain underscores because we need to differentiate them from invalid plugin types.
  813. if (substr_count($param, '_') != 1) {
  814. return '';
  815. }
  816. }
  817. return $param;
  818. case PARAM_PLUGIN:
  819. case PARAM_AREA:
  820. // We do not want any guessing here, either the name is correct or not.
  821. if (!is_valid_plugin_name($param)) {
  822. return '';
  823. }
  824. return $param;
  825. case PARAM_SAFEDIR:
  826. // Remove everything not a-zA-Z0-9_- .
  827. return preg_replace('/[^a-zA-Z0-9_-]/i', '', $param);
  828. case PARAM_SAFEPATH:
  829. // Remove everything not a-zA-Z0-9/_- .
  830. return preg_replace('/[^a-zA-Z0-9\/_-]/i', '', $param);
  831. case PARAM_FILE:
  832. // Strip all suspicious characters from filename.
  833. $param = fix_utf8($param);
  834. $param = preg_replace('~[[:cntrl:]]|[&<>"`\|\':\\\\/]~u', '', $param);
  835. if ($param === '.' || $param === '..') {
  836. $param = '';
  837. }
  838. return $param;
  839. case PARAM_PATH:
  840. // Strip all suspicious characters from file path.
  841. $param = fix_utf8($param);
  842. $param = str_replace('\\', '/', $param);
  843. // Explode the path and clean each element using the PARAM_FILE rules.
  844. $breadcrumb = explode('/', $param);
  845. foreach ($breadcrumb as $key => $crumb) {
  846. if ($crumb === '.' && $key === 0) {
  847. // Special condition to allow for relative current path such as ./currentdirfile.txt.
  848. } else {
  849. $crumb = clean_param($crumb, PARAM_FILE);
  850. }
  851. $breadcrumb[$key] = $crumb;
  852. }
  853. $param = implode('/', $breadcrumb);
  854. // Remove multiple current path (./././) and multiple slashes (///).
  855. $param = preg_replace('~//+~', '/', $param);
  856. $param = preg_replace('~/(\./)+~', '/', $param);
  857. return $param;
  858. case PARAM_HOST:
  859. // Allow FQDN or IPv4 dotted quad.
  860. $param = preg_replace('/[^\.\d\w-]/', '', $param );
  861. // Match ipv4 dotted quad.
  862. if (preg_match('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', $param, $match)) {
  863. // Confirm values are ok.
  864. if ( $match[0] > 255
  865. || $match[1] > 255
  866. || $match[3] > 255
  867. || $match[4] > 255 ) {
  868. // Hmmm, what kind of dotted quad is this?
  869. $param = '';
  870. }
  871. } else if ( preg_match('/^[\w\d\.-]+$/', $param) // Dots, hyphens, numbers.
  872. && !preg_match('/^[\.-]/', $param) // No leading dots/hyphens.
  873. && !preg_match('/[\.-]$/', $param) // No trailing dots/hyphens.
  874. ) {
  875. // All is ok - $param is respected.
  876. } else {
  877. // All is not ok...
  878. $param='';
  879. }
  880. return $param;
  881. case PARAM_URL: // Allow safe ftp, http, mailto urls.
  882. $param = fix_utf8($param);
  883. include_once($CFG->dirroot . '/lib/validateurlsyntax.php');
  884. if (!empty($param) && validateUrlSyntax($param, 's?H?S?F?E?u-P-a?I?p?f?q?r?')) {
  885. // All is ok, param is respected.
  886. } else {
  887. // Not really ok.
  888. $param ='';
  889. }
  890. return $param;
  891. case PARAM_LOCALURL:
  892. // Allow http absolute, root relative and relative URLs within wwwroot.
  893. $param = clean_param($param, PARAM_URL);
  894. if (!empty($param)) {
  895. if (preg_match(':^/:', $param)) {
  896. // Root-relative, ok!
  897. } else if (preg_match('/^'.preg_quote($CFG->wwwroot, '/').'/i', $param)) {
  898. // Absolute, and matches our wwwroot.
  899. } else {
  900. // Relative - let's make sure there are no tricks.
  901. if (validateUrlSyntax('/' . $param, 's-u-P-a-p-f+q?r?')) {
  902. // Looks ok.
  903. } else {
  904. $param = '';
  905. }
  906. }
  907. }
  908. return $param;
  909. case PARAM_PEM:
  910. $param = trim($param);
  911. // PEM formatted strings may contain letters/numbers and the symbols:
  912. // forward slash: /
  913. // plus sign: +
  914. // equal sign: =
  915. // , surrounded by BEGIN and END CERTIFICATE prefix and suffixes.
  916. if (preg_match('/^-----BEGIN CERTIFICATE-----([\s\w\/\+=]+)-----END CERTIFICATE-----$/', trim($param), $matches)) {
  917. list($wholething, $body) = $matches;
  918. unset($wholething, $matches);
  919. $b64 = clean_param($body, PARAM_BASE64);
  920. if (!empty($b64)) {
  921. return "-----BEGIN CERTIFICATE-----\n$b64\n-----END CERTIFICATE-----\n";
  922. } else {
  923. return '';
  924. }
  925. }
  926. return '';
  927. case PARAM_BASE64:
  928. if (!empty($param)) {
  929. // PEM formatted strings may contain letters/numbers and the symbols
  930. // forward slash: /
  931. // plus sign: +
  932. // equal sign: =.
  933. if (0 >= preg_match('/^([\s\w\/\+=]+)$/', trim($param))) {
  934. return '';
  935. }
  936. $lines = preg_split('/[\s]+/', $param, -1, PREG_SPLIT_NO_EMPTY);
  937. // Each line of base64 encoded data must be 64 characters in length, except for the last line which may be less
  938. // than (or equal to) 64 characters long.
  939. for ($i=0, $j=count($lines); $i < $j; $i++) {
  940. if ($i + 1 == $j) {
  941. if (64 < strlen($lines[$i])) {
  942. return '';
  943. }
  944. continue;
  945. }
  946. if (64 != strlen($lines[$i])) {
  947. return '';
  948. }
  949. }
  950. return implode("\n", $lines);
  951. } else {
  952. return '';
  953. }
  954. case PARAM_TAG:
  955. $param = fix_utf8($param);
  956. // Please note it is not safe to use the tag name directly anywhere,
  957. // it must be processed with s(), urlencode() before embedding anywhere.
  958. // Remove some nasties.
  959. $param = preg_replace('~[[:cntrl:]]|[<>`]~u', '', $param);
  960. // Convert many whitespace chars into one.
  961. $param = preg_replace('/\s+/', ' ', $param);
  962. $param = core_text::substr(trim($param), 0, TAG_MAX_LENGTH);
  963. return $param;
  964. case PARAM_TAGLIST:
  965. $param = fix_utf8($param);
  966. $tags = explode(',', $param);
  967. $result = array();
  968. foreach ($tags as $tag) {
  969. $res = clean_param($tag, PARAM_TAG);
  970. if ($res !== '') {
  971. $result[] = $res;
  972. }
  973. }
  974. if ($result) {
  975. return implode(',', $result);
  976. } else {
  977. return '';
  978. }
  979. case PARAM_CAPABILITY:
  980. if (get_capability_info($param)) {
  981. return $param;
  982. } else {
  983. return '';
  984. }
  985. case PARAM_PERMISSION:
  986. $param = (int)$param;
  987. if (in_array($param, array(CAP_INHERIT, CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT))) {
  988. return $param;
  989. } else {
  990. return CAP_INHERIT;
  991. }
  992. case PARAM_AUTH:
  993. $param = clean_param($param, PARAM_PLUGIN);
  994. if (empty($param)) {
  995. return '';
  996. } else if (exists_auth_plugin($param)) {
  997. return $param;
  998. } else {
  999. return '';
  1000. }
  1001. case PARAM_LANG:
  1002. $param = clean_param($param, PARAM_SAFEDIR);
  1003. if (get_string_manager()->translation_exists($param)) {
  1004. return $param;
  1005. } else {
  1006. // Specified language is not installed or param malformed.
  1007. return '';
  1008. }
  1009. case PARAM_THEME:
  1010. $param = clean_param($param, PARAM_PLUGIN);
  1011. if (empty($param)) {
  1012. return '';
  1013. } else if (file_exists("$CFG->dirroot/theme/$param/config.php")) {
  1014. return $param;
  1015. } else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$param/config.php")) {
  1016. return $param;
  1017. } else {
  1018. // Specified theme is not installed.
  1019. return '';
  1020. }
  1021. case PARAM_USERNAME:
  1022. $param = fix_utf8($param);
  1023. $param = str_replace(" " , "", $param);
  1024. // Convert uppercase to lowercase MDL-16919.
  1025. $param = core_text::strtolower($param);
  1026. if (empty($CFG->extendedusernamechars)) {
  1027. // Regular expression, eliminate all chars EXCEPT:
  1028. // alphanum, dash (-), underscore (_), at sign (@) and period (.) characters.
  1029. $param = preg_replace('/[^-\.@_a-z0-9]/', '', $param);
  1030. }
  1031. return $param;
  1032. case PARAM_EMAIL:
  1033. $param = fix_utf8($param);
  1034. if (validate_email($param)) {
  1035. return $param;
  1036. } else {
  1037. return '';
  1038. }
  1039. case PARAM_STRINGID:
  1040. if (preg_match('|^[a-zA-Z][a-zA-Z0-9\.:/_-]*$|', $param)) {
  1041. return $param;
  1042. } else {
  1043. return '';
  1044. }
  1045. case PARAM_TIMEZONE:
  1046. // Can be int, float(with .5 or .0) or string seperated by '/' and can have '-_'.
  1047. $param = fix_utf8($param);
  1048. $timezonepattern = '/^(([+-]?(0?[0-9](\.[5|0])?|1[0-3](\.0)?|1[0-2]\.5))|(99)|[[:alnum:]]+(\/?[[:alpha:]_-])+)$/';
  1049. if (preg_match($timezonepattern, $param)) {
  1050. return $param;
  1051. } else {
  1052. return '';
  1053. }
  1054. default:
  1055. // Doh! throw error, switched parameters in optional_param or another serious problem.
  1056. print_error("unknownparamtype", '', '', $type);
  1057. }
  1058. }
  1059. /**
  1060. * Makes sure the data is using valid utf8, invalid characters are discarded.
  1061. *
  1062. * Note: this function is not intended for full objects with methods and private properties.
  1063. *
  1064. * @param mixed $value
  1065. * @return mixed with proper utf-8 encoding
  1066. */
  1067. function fix_utf8($value) {
  1068. if (is_null($value) or $value === '') {
  1069. return $value;
  1070. } else if (is_string($value)) {
  1071. if ((string)(int)$value === $value) {
  1072. // Shortcut.
  1073. return $value;
  1074. }
  1075. // No null bytes expected in our data, so let's remove it.
  1076. $value = str_replace("\0", '', $value);
  1077. // Note: this duplicates min_fix_utf8() intentionally.
  1078. static $buggyiconv = null;
  1079. if ($buggyiconv === null) {
  1080. $buggyiconv = (!function_exists('iconv') or @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
  1081. }
  1082. if ($buggyiconv) {
  1083. if (function_exists('mb_convert_encoding')) {
  1084. $subst = mb_substitute_character();
  1085. mb_substitute_character('');
  1086. $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
  1087. mb_substitute_character($subst);
  1088. } else {
  1089. // Warn admins on admin/index.php page.
  1090. $result = $value;
  1091. }
  1092. } else {
  1093. $result = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
  1094. }
  1095. return $result;
  1096. } else if (is_array($value)) {
  1097. foreach ($value as $k => $v) {
  1098. $value[$k] = fix_utf8($v);
  1099. }
  1100. return $value;
  1101. } else if (is_object($value)) {
  1102. // Do not modify original.
  1103. $value = clone($value);
  1104. foreach ($value as $k => $v) {
  1105. $value->$k = fix_utf8($v);
  1106. }
  1107. return $value;
  1108. } else {
  1109. // This is some other type, no utf-8 here.
  1110. return $value;
  1111. }
  1112. }
  1113. /**
  1114. * Return true if given value is integer or string with integer value
  1115. *
  1116. * @param mixed $value String or Int
  1117. * @return bool true if number, false if not
  1118. */
  1119. function is_number($value) {
  1120. if (is_int($value)) {
  1121. return true;
  1122. } else if (is_string($value)) {
  1123. return ((string)(int)$value) === $value;
  1124. } else {
  1125. return false;
  1126. }
  1127. }
  1128. /**
  1129. * Returns host part from url.
  1130. *
  1131. * @param string $url full url
  1132. * @return string host, null if not found
  1133. */
  1134. function get_host_from_url($url) {
  1135. preg_match('|^[a-z]+://([a-zA-Z0-9-.]+)|i', $url, $matches);
  1136. if ($matches) {
  1137. return $matches[1];
  1138. }
  1139. return null;
  1140. }
  1141. /**
  1142. * Tests whether anything was returned by text editor
  1143. *
  1144. * This function is useful for testing whether something you got back from
  1145. * the HTML editor actually contains anything. Sometimes the HTML editor
  1146. * appear to be empty, but actually you get back a <br> tag or something.
  1147. *
  1148. * @param string $string a string containing HTML.
  1149. * @return boolean does the string contain any actual content - that is text,
  1150. * images, objects, etc.
  1151. */
  1152. function html_is_blank($string) {
  1153. return trim(strip_tags($string, '<img><object><applet><input><select><textarea><hr>')) == '';
  1154. }
  1155. /**
  1156. * Set a key in global configuration
  1157. *
  1158. * Set a key/value pair in both this session's {@link $CFG} global variable
  1159. * and in the 'config' database table for future sessions.
  1160. *
  1161. * Can also be used to update keys for plugin-scoped configs in config_plugin table.
  1162. * In that case it doesn't affect $CFG.
  1163. *
  1164. * A NULL value will delete the entry.
  1165. *
  1166. * NOTE: this function is called from lib/db/upgrade.php
  1167. *
  1168. * @param string $name the key to set
  1169. * @param string $value the value to set (without magic quotes)
  1170. * @param string $plugin (optional) the plugin scope, default null
  1171. * @return bool true or exception
  1172. */
  1173. function set_config($name, $value, $plugin=null) {
  1174. global $CFG, $DB;
  1175. if (empty($plugin)) {
  1176. if (!array_key_exists($name, $CFG->config_php_settings)) {
  1177. // So it's defined for this invocation at least.
  1178. if (is_null($value)) {
  1179. unset($CFG->$name);
  1180. } else {
  1181. // Settings from db are always strings.
  1182. $CFG->$name = (string)$value;
  1183. }
  1184. }
  1185. if ($DB->get_field('config', 'name', array('name' => $name))) {
  1186. if ($value === null) {
  1187. $DB->delete_records('config', array('name' => $name));
  1188. } else {
  1189. $DB->set_field('config', 'value', $value, array('name' => $name));
  1190. }
  1191. } else {
  1192. if ($value !== null) {
  1193. $config = new stdClass();
  1194. $config->name = $name;
  1195. $config->value = $value;
  1196. $DB->insert_record('config', $config, false);
  1197. }
  1198. }
  1199. if ($name === 'siteidentifier') {
  1200. cache_helper::update_site_identifier($value);
  1201. }
  1202. cache_helper::invalidate_by_definition('core', 'config', array(), 'core');
  1203. } else {
  1204. // Plugin scope.
  1205. if ($id = $DB->get_field('config_plugins', 'id', array('name' => $name, 'plugin' => $plugin))) {
  1206. if ($value===null) {
  1207. $DB->delete_records('config_plugins', array('name' => $name, 'plugin' => $plugin));
  1208. } else {
  1209. $DB->set_field('config_plugins', 'value', $value, array('id' => $id));
  1210. }
  1211. } else {
  1212. if ($value !== null) {
  1213. $config = new stdClass();
  1214. $config->plugin = $plugin;
  1215. $config->name = $name;
  1216. $config->value = $value;
  1217. $DB->insert_record('config_plugins', $config, false);
  1218. }
  1219. }
  1220. cache_helper::invalidate_by_definition('core', 'config', array(), $plugin);
  1221. }
  1222. return true;
  1223. }
  1224. /**
  1225. * Get configuration values from the global config table
  1226. * or the config_plugins table.
  1227. *
  1228. * If called with one parameter, it will load all the config
  1229. * variables for one plugin, and return them as an object.
  1230. *
  1231. * If called with 2 parameters it will return a string single
  1232. * value or false if the value is not found.
  1233. *
  1234. * NOTE: this function is called from lib/db/upgrade.php
  1235. *
  1236. * @static string|false $siteidentifier The site identifier is not cached. We use this static cache so
  1237. * that we need only fetch it once per request.
  1238. * @param string $plugin full component name
  1239. * @param string $name default null
  1240. * @return mixed hash-like object or single value, return false no config found
  1241. * @throws dml_exception
  1242. */
  1243. function get_config($plugin, $name = null) {
  1244. global $CFG, $DB;
  1245. static $siteidentifier = null;
  1246. if ($plugin === 'moodle' || $plugin === 'core' || empty($plugin)) {
  1247. $forced =& $CFG->config_php_settings;
  1248. $iscore = true;
  1249. $plugin = 'core';
  1250. } else {
  1251. if (array_key_exists($plugin, $CFG->forced_plugin_settings)) {
  1252. $forced =& $CFG->forced_plugin_settings[$plugin];
  1253. } else {
  1254. $forced = array();
  1255. }
  1256. $iscore = false;
  1257. }
  1258. if ($siteidentifier === null) {
  1259. try {
  1260. // This may fail during installation.
  1261. // If you have a look at {@link initialise_cfg()} you will see that this is how we detect the need to
  1262. // install the database.
  1263. $siteidentifier = $DB->get_field('config', 'value', array('name' => 'siteidentifier'));
  1264. } catch (dml_exception $ex) {
  1265. // Set siteidentifier to false. We don't want to trip this continually.
  1266. $siteidentifier = false;
  1267. throw $ex;
  1268. }
  1269. }
  1270. if (!empty($name)) {
  1271. if (array_key_exists($name, $forced)) {
  1272. return (string)$forced[$name];
  1273. } else if ($name === 'siteidentifier' && $plugin == 'core') {
  1274. return $siteidentifier;
  1275. }
  1276. }
  1277. $cache = cache::make('core', 'config');
  1278. $result = $cache->get($plugin);
  1279. if ($result === false) {
  1280. // The user is after a recordset.
  1281. if (!$iscore) {
  1282. $result = $DB->get_records_menu('config_plugins', array('plugin' => $plugin), '', 'name,value');
  1283. } else {
  1284. // This part is not really used any more, but anyway...
  1285. $result = $DB->get_records_menu('c…

Large files files are truncated, but you can click here to view the full file