PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/engine/lib/configuration.php

https://github.com/fragilbert/Elgg
PHP | 631 lines | 316 code | 84 blank | 231 comment | 68 complexity | e53d887c987429d26693e017caefcaec MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, LGPL-2.1, GPL-2.0
  1. <?php
  2. /**
  3. * Elgg configuration procedural code.
  4. *
  5. * Includes functions for manipulating the configuration values stored in the database
  6. * Plugin authors should use the {@link elgg_get_config()}, {@link elgg_set_config()},
  7. * {@link elgg_save_config()}, and {@unset_config()} functions to access or update
  8. * config values.
  9. *
  10. * Elgg's configuration is split among 2 tables and 1 file:
  11. * - dbprefix_config
  12. * - dbprefix_datalists
  13. * - engine/settings.php (See {@link settings.example.php})
  14. *
  15. * Upon system boot, all values in dbprefix_config are read into $CONFIG.
  16. *
  17. * @package Elgg.Core
  18. * @subpackage Configuration
  19. */
  20. /**
  21. * Get the URL for the current (or specified) site
  22. *
  23. * @param int $site_guid The GUID of the site whose URL we want to grab
  24. * @return string
  25. * @since 1.8.0
  26. */
  27. function elgg_get_site_url($site_guid = 0) {
  28. if ($site_guid == 0) {
  29. global $CONFIG;
  30. return $CONFIG->wwwroot;
  31. }
  32. $site = get_entity($site_guid);
  33. if (!$site instanceof ElggSite) {
  34. return false;
  35. }
  36. /* @var ElggSite $site */
  37. return $site->url;
  38. }
  39. /**
  40. * Get the plugin path for this installation
  41. *
  42. * @return string
  43. * @since 1.8.0
  44. */
  45. function elgg_get_plugins_path() {
  46. global $CONFIG;
  47. return $CONFIG->pluginspath;
  48. }
  49. /**
  50. * Get the data directory path for this installation
  51. *
  52. * @return string
  53. * @since 1.8.0
  54. */
  55. function elgg_get_data_path() {
  56. global $CONFIG;
  57. return $CONFIG->dataroot;
  58. }
  59. /**
  60. * Get the root directory path for this installation
  61. *
  62. * @return string
  63. * @since 1.8.0
  64. */
  65. function elgg_get_root_path() {
  66. global $CONFIG;
  67. return $CONFIG->path;
  68. }
  69. /**
  70. * Get an Elgg configuration value
  71. *
  72. * @param string $name Name of the configuration value
  73. * @param int $site_guid NULL for installation setting, 0 for default site
  74. *
  75. * @return mixed Configuration value or null if it does not exist
  76. * @since 1.8.0
  77. */
  78. function elgg_get_config($name, $site_guid = 0) {
  79. global $CONFIG;
  80. $name = trim($name);
  81. if (isset($CONFIG->$name)) {
  82. return $CONFIG->$name;
  83. }
  84. if ($site_guid === null) {
  85. // installation wide setting
  86. $value = datalist_get($name);
  87. } else {
  88. // hit DB only if we're not sure if value exists or not
  89. if (!isset($CONFIG->site_config_loaded)) {
  90. // site specific setting
  91. if ($site_guid == 0) {
  92. $site_guid = (int) $CONFIG->site_id;
  93. }
  94. $value = get_config($name, $site_guid);
  95. } else {
  96. $value = null;
  97. }
  98. }
  99. // @todo document why we don't cache false
  100. if ($value === false) {
  101. return null;
  102. }
  103. $CONFIG->$name = $value;
  104. return $value;
  105. }
  106. /**
  107. * Set an Elgg configuration value
  108. *
  109. * @warning This does not persist the configuration setting. Use elgg_save_config()
  110. *
  111. * @param string $name Name of the configuration value
  112. * @param mixed $value Value
  113. *
  114. * @return void
  115. * @since 1.8.0
  116. */
  117. function elgg_set_config($name, $value) {
  118. global $CONFIG;
  119. $name = trim($name);
  120. $CONFIG->$name = $value;
  121. }
  122. /**
  123. * Save a configuration setting
  124. *
  125. * @param string $name Configuration name (cannot be greater than 255 characters)
  126. * @param mixed $value Configuration value. Should be string for installation setting
  127. * @param int $site_guid NULL for installation setting, 0 for default site
  128. *
  129. * @return bool
  130. * @since 1.8.0
  131. */
  132. function elgg_save_config($name, $value, $site_guid = 0) {
  133. global $CONFIG;
  134. $name = trim($name);
  135. if (strlen($name) > 255) {
  136. elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
  137. return false;
  138. }
  139. elgg_set_config($name, $value);
  140. if ($site_guid === NULL) {
  141. if (is_array($value) || is_object($value)) {
  142. return false;
  143. }
  144. return datalist_set($name, $value);
  145. } else {
  146. if ($site_guid == 0) {
  147. $site_guid = (int) $CONFIG->site_id;
  148. }
  149. return set_config($name, $value, $site_guid);
  150. }
  151. }
  152. /**
  153. * Check that installation has completed and the database is populated.
  154. *
  155. * @throws InstallationException|DatabaseException
  156. * @return void
  157. * @access private
  158. */
  159. function verify_installation() {
  160. global $CONFIG;
  161. if (isset($CONFIG->installed)) {
  162. return;
  163. }
  164. try {
  165. $dblink = get_db_link('read');
  166. if (!$dblink) {
  167. throw new DatabaseException();
  168. }
  169. mysql_query("SELECT value FROM {$CONFIG->dbprefix}datalists WHERE name = 'installed'", $dblink);
  170. if (mysql_errno($dblink) > 0) {
  171. throw new DatabaseException();
  172. }
  173. $CONFIG->installed = true;
  174. } catch (DatabaseException $e) {
  175. throw new InstallationException(elgg_echo('InstallationException:SiteNotInstalled'));
  176. }
  177. }
  178. /**
  179. * An array of key value pairs from the datalists table.
  180. *
  181. * Used as a cache in datalist functions.
  182. *
  183. * @global array $DATALIST_CACHE
  184. */
  185. $DATALIST_CACHE = array();
  186. /**
  187. * Get the value of a datalist element.
  188. *
  189. * @internal Datalists are stored in the datalist table.
  190. *
  191. * @tip Use datalists to store information common to a full installation.
  192. *
  193. * @param string $name The name of the datalist
  194. * @return string|null|false String if value exists, null if doesn't, false on error
  195. * @access private
  196. */
  197. function datalist_get($name) {
  198. global $CONFIG, $DATALIST_CACHE;
  199. $name = trim($name);
  200. // cannot store anything longer than 255 characters in db, so catch here
  201. if (elgg_strlen($name) > 255) {
  202. elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
  203. return false;
  204. }
  205. $name = sanitise_string($name);
  206. if (isset($DATALIST_CACHE[$name])) {
  207. return $DATALIST_CACHE[$name];
  208. }
  209. // If memcache enabled then cache value in memcache
  210. $value = null;
  211. static $datalist_memcache;
  212. if ((!$datalist_memcache) && (is_memcache_available())) {
  213. $datalist_memcache = new ElggMemcache('datalist_memcache');
  214. }
  215. if ($datalist_memcache) {
  216. $value = $datalist_memcache->load($name);
  217. }
  218. if ($value) {
  219. return $value;
  220. }
  221. // [Marcus Povey 20090217 : Now retrieving all datalist values on first
  222. // load as this saves about 9 queries per page]
  223. // This also causes OOM problems when the datalists table is large
  224. // @todo make a list of datalists that we want to get in one grab
  225. $result = get_data("SELECT * from {$CONFIG->dbprefix}datalists");
  226. if ($result) {
  227. foreach ($result as $row) {
  228. $DATALIST_CACHE[$row->name] = $row->value;
  229. // Cache it if memcache is available
  230. if ($datalist_memcache) {
  231. $datalist_memcache->save($row->name, $row->value);
  232. }
  233. }
  234. if (isset($DATALIST_CACHE[$name])) {
  235. return $DATALIST_CACHE[$name];
  236. }
  237. }
  238. return null;
  239. }
  240. /**
  241. * Set the value for a datalist element.
  242. *
  243. * @param string $name The name of the datalist
  244. * @param string $value The new value
  245. *
  246. * @return bool
  247. * @access private
  248. */
  249. function datalist_set($name, $value) {
  250. global $CONFIG, $DATALIST_CACHE;
  251. // cannot store anything longer than 255 characters in db, so catch before we set
  252. if (elgg_strlen($name) > 255) {
  253. elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
  254. return false;
  255. }
  256. $sanitised_name = sanitise_string($name);
  257. $sanitised_value = sanitise_string($value);
  258. // If memcache is available then invalidate the cached copy
  259. static $datalist_memcache;
  260. if ((!$datalist_memcache) && (is_memcache_available())) {
  261. $datalist_memcache = new ElggMemcache('datalist_memcache');
  262. }
  263. if ($datalist_memcache) {
  264. $datalist_memcache->delete($name);
  265. }
  266. $success = insert_data("INSERT into {$CONFIG->dbprefix}datalists"
  267. . " set name = '{$sanitised_name}', value = '{$sanitised_value}'"
  268. . " ON DUPLICATE KEY UPDATE value='{$sanitised_value}'");
  269. if ($success !== FALSE) {
  270. $DATALIST_CACHE[$name] = $value;
  271. return true;
  272. } else {
  273. return false;
  274. }
  275. }
  276. /**
  277. * Run a function one time per installation.
  278. *
  279. * If you pass a timestamp as the second argument, it will run the function
  280. * only if (i) it has never been run before or (ii) the timestamp is >=
  281. * the last time it was run.
  282. *
  283. * @warning Functions are determined by their name. If you change the name of a function
  284. * it will be run again.
  285. *
  286. * @tip Use $timelastupdatedcheck in your plugins init function to perform automated
  287. * upgrades. Schedule a function to run once and pass the timestamp of the new release.
  288. * This will cause the run once function to be run on all installations. To perform
  289. * additional upgrades, create new functions for each release.
  290. *
  291. * @warning The function name cannot be longer than 255 characters long due to
  292. * the current schema for the datalist table.
  293. *
  294. * @internal A datalist entry $functioname is created with the value of time().
  295. *
  296. * @param string $functionname The name of the function you want to run.
  297. * @param int $timelastupdatedcheck A UNIX timestamp. If time() is > than this,
  298. * this function will be run again.
  299. *
  300. * @return bool
  301. */
  302. function run_function_once($functionname, $timelastupdatedcheck = 0) {
  303. $lastupdated = datalist_get($functionname);
  304. if ($lastupdated) {
  305. $lastupdated = (int) $lastupdated;
  306. } elseif ($lastupdated !== false) {
  307. $lastupdated = 0;
  308. } else {
  309. // unable to check datalist
  310. return false;
  311. }
  312. if (is_callable($functionname) && $lastupdated <= $timelastupdatedcheck) {
  313. $functionname();
  314. datalist_set($functionname, time());
  315. return true;
  316. } else {
  317. return false;
  318. }
  319. }
  320. /**
  321. * Removes a config setting.
  322. *
  323. * @internal
  324. * These settings are stored in the dbprefix_config table and read during system
  325. * boot into $CONFIG.
  326. *
  327. * @param string $name The name of the field.
  328. * @param int $site_guid Optionally, the GUID of the site (current site is assumed by default).
  329. *
  330. * @return int|false The number of affected rows or false on error.
  331. *
  332. * @see get_config()
  333. * @see set_config()
  334. */
  335. function unset_config($name, $site_guid = 0) {
  336. global $CONFIG;
  337. if (isset($CONFIG->$name)) {
  338. unset($CONFIG->$name);
  339. }
  340. $name = sanitise_string($name);
  341. $site_guid = (int) $site_guid;
  342. if ($site_guid == 0) {
  343. $site_guid = (int) $CONFIG->site_id;
  344. }
  345. $query = "delete from {$CONFIG->dbprefix}config where name='$name' and site_guid=$site_guid";
  346. return delete_data($query);
  347. }
  348. /**
  349. * Add or update a config setting.
  350. *
  351. * If the config name already exists, it will be updated to the new value.
  352. *
  353. * @internal
  354. * These settings are stored in the dbprefix_config table and read during system
  355. * boot into $CONFIG.
  356. *
  357. * @param string $name The name of the configuration value
  358. * @param string $value Its value
  359. * @param int $site_guid Optionally, the GUID of the site (current site is assumed by default)
  360. *
  361. * @return bool
  362. * @todo The config table doens't have numeric primary keys so insert_data returns 0.
  363. * @todo Use "INSERT ... ON DUPLICATE KEY UPDATE" instead of trying to delete then add.
  364. * @see unset_config()
  365. * @see get_config()
  366. * @access private
  367. */
  368. function set_config($name, $value, $site_guid = 0) {
  369. global $CONFIG;
  370. $name = trim($name);
  371. // cannot store anything longer than 255 characters in db, so catch before we set
  372. if (elgg_strlen($name) > 255) {
  373. elgg_log("The name length for configuration variables cannot be greater than 255", "ERROR");
  374. return false;
  375. }
  376. // Unset existing
  377. unset_config($name, $site_guid);
  378. $site_guid = (int) $site_guid;
  379. if ($site_guid == 0) {
  380. $site_guid = (int) $CONFIG->site_id;
  381. }
  382. $CONFIG->$name = $value;
  383. $value = sanitise_string(serialize($value));
  384. $query = "insert into {$CONFIG->dbprefix}config"
  385. . " set name = '{$name}', value = '{$value}', site_guid = {$site_guid}";
  386. $result = insert_data($query);
  387. return $result !== false;
  388. }
  389. /**
  390. * Gets a configuration value
  391. *
  392. * @internal
  393. * These settings are stored in the dbprefix_config table and read during system
  394. * boot into $CONFIG.
  395. *
  396. * @param string $name The name of the config value
  397. * @param int $site_guid Optionally, the GUID of the site (current site is assumed by default)
  398. *
  399. * @return mixed|null
  400. * @see set_config()
  401. * @see unset_config()
  402. * @access private
  403. */
  404. function get_config($name, $site_guid = 0) {
  405. global $CONFIG;
  406. $name = sanitise_string($name);
  407. $site_guid = (int) $site_guid;
  408. // check for deprecated values.
  409. // @todo might be a better spot to define this?
  410. $new_name = false;
  411. switch($name) {
  412. case 'viewpath':
  413. $new_name = 'view_path';
  414. $dep_version = 1.8;
  415. break;
  416. case 'pluginspath':
  417. $new_name = 'plugins_path';
  418. $dep_version = 1.8;
  419. break;
  420. case 'sitename':
  421. $new_name = 'site_name';
  422. $dep_version = 1.8;
  423. break;
  424. }
  425. // @todo these haven't really been implemented in Elgg 1.8. Complete in 1.9.
  426. // show dep message
  427. if ($new_name) {
  428. // $msg = "Config value $name has been renamed as $new_name";
  429. $name = $new_name;
  430. // elgg_deprecated_notice($msg, $dep_version);
  431. }
  432. // decide from where to return the value
  433. if (isset($CONFIG->$name)) {
  434. return $CONFIG->$name;
  435. }
  436. if ($site_guid == 0) {
  437. $site_guid = (int) $CONFIG->site_id;
  438. }
  439. $result = get_data_row("SELECT value FROM {$CONFIG->dbprefix}config
  440. WHERE name = '{$name}' and site_guid = {$site_guid}");
  441. if ($result) {
  442. $result = $result->value;
  443. $result = unserialize($result->value);
  444. $CONFIG->$name = $result;
  445. return $result;
  446. }
  447. return null;
  448. }
  449. /**
  450. * Loads all configuration values from the dbprefix_config table into $CONFIG.
  451. *
  452. * @param int $site_guid Optionally, the GUID of the site (current site is assumed by default)
  453. *
  454. * @return bool
  455. * @access private
  456. */
  457. function get_all_config($site_guid = 0) {
  458. global $CONFIG;
  459. $site_guid = (int) $site_guid;
  460. if ($site_guid == 0) {
  461. $site_guid = (int) $CONFIG->site_guid;
  462. }
  463. if ($result = get_data("SELECT * FROM {$CONFIG->dbprefix}config WHERE site_guid = $site_guid")) {
  464. foreach ($result as $r) {
  465. $name = $r->name;
  466. $value = $r->value;
  467. $CONFIG->$name = unserialize($value);
  468. }
  469. return true;
  470. }
  471. return false;
  472. }
  473. /**
  474. * Loads configuration related to this site
  475. *
  476. * This loads from the config database table and the site entity
  477. * @access private
  478. */
  479. function _elgg_load_site_config() {
  480. global $CONFIG;
  481. $CONFIG->site_guid = (int) datalist_get('default_site');
  482. $CONFIG->site_id = $CONFIG->site_guid;
  483. $CONFIG->site = get_entity($CONFIG->site_guid);
  484. if (!$CONFIG->site) {
  485. throw new InstallationException(elgg_echo('InstallationException:SiteNotInstalled'));
  486. }
  487. $CONFIG->wwwroot = $CONFIG->site->url;
  488. $CONFIG->sitename = $CONFIG->site->name;
  489. $CONFIG->sitedescription = $CONFIG->site->description;
  490. $CONFIG->siteemail = $CONFIG->site->email;
  491. $CONFIG->url = $CONFIG->wwwroot;
  492. get_all_config();
  493. if (!empty($CONFIG->debug)) {
  494. _elgg_services()->logger->setLevel($CONFIG->debug);
  495. }
  496. }
  497. /**
  498. * Loads configuration related to Elgg as an application
  499. *
  500. * This loads from the datalists database table
  501. * @access private
  502. */
  503. function _elgg_load_application_config() {
  504. global $CONFIG;
  505. $install_root = str_replace("\\", "/", dirname(dirname(dirname(__FILE__))));
  506. $defaults = array(
  507. 'path' => "$install_root/",
  508. 'view_path' => "$install_root/views/",
  509. 'plugins_path' => "$install_root/mod/",
  510. 'language' => 'en',
  511. // compatibility with old names for plugins not using elgg_get_config()
  512. 'viewpath' => "$install_root/views/",
  513. 'pluginspath' => "$install_root/mod/",
  514. );
  515. foreach ($defaults as $name => $value) {
  516. if (empty($CONFIG->$name)) {
  517. $CONFIG->$name = $value;
  518. }
  519. }
  520. $path = datalist_get('path');
  521. if (!empty($path)) {
  522. $CONFIG->path = $path;
  523. }
  524. $dataroot = datalist_get('dataroot');
  525. if (!empty($dataroot)) {
  526. $CONFIG->dataroot = $dataroot;
  527. }
  528. $simplecache_enabled = datalist_get('simplecache_enabled');
  529. if ($simplecache_enabled !== false) {
  530. $CONFIG->simplecache_enabled = $simplecache_enabled;
  531. } else {
  532. $CONFIG->simplecache_enabled = 1;
  533. }
  534. $system_cache_enabled = datalist_get('system_cache_enabled');
  535. if ($system_cache_enabled !== false) {
  536. $CONFIG->system_cache_enabled = $system_cache_enabled;
  537. } else {
  538. $CONFIG->system_cache_enabled = 1;
  539. }
  540. // initialize context here so it is set before the get_input call
  541. $CONFIG->context = array();
  542. // needs to be set before system, init for links in html head
  543. $CONFIG->lastcache = datalist_get("simplecache_lastupdate");
  544. $CONFIG->i18n_loaded_from_cache = false;
  545. // this must be synced with the enum for the entities table
  546. $CONFIG->entity_types = array('group', 'object', 'site', 'user');
  547. }