PageRenderTime 72ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 3ms

/lib/moodlelib.php

https://bitbucket.org/ngmares/moodle
PHP | 10996 lines | 6251 code | 1374 blank | 3371 comment | 1527 complexity | fbb73babaa355e854f73a97939e09b8c MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-3.0, Apache-2.0, BSD-3-Clause

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

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