PageRenderTime 85ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/core/lib/Drupal/Core/Site/Settings.php

http://github.com/drupal/drupal
PHP | 194 lines | 63 code | 20 blank | 111 comment | 8 complexity | e0a18e69a7a9d2376b27666d6b6d6ff5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. namespace Drupal\Core\Site;
  3. use Drupal\Component\Utility\Crypt;
  4. use Drupal\Core\Database\Database;
  5. /**
  6. * Read only settings that are initialized with the class.
  7. *
  8. * @ingroup utility
  9. */
  10. final class Settings {
  11. /**
  12. * Array with the settings.
  13. *
  14. * @var array
  15. */
  16. private $storage = [];
  17. /**
  18. * Singleton instance.
  19. *
  20. * @var \Drupal\Core\Site\Settings
  21. */
  22. private static $instance = NULL;
  23. /**
  24. * Constructor.
  25. *
  26. * @param array $settings
  27. * Array with the settings.
  28. */
  29. public function __construct(array $settings) {
  30. $this->storage = $settings;
  31. self::$instance = $this;
  32. }
  33. /**
  34. * Returns the settings instance.
  35. *
  36. * A singleton is used because this class is used before the container is
  37. * available.
  38. *
  39. * @return \Drupal\Core\Site\Settings
  40. *
  41. * @throws \BadMethodCallException
  42. * Thrown when the settings instance has not been initialized yet.
  43. */
  44. public static function getInstance() {
  45. if (self::$instance === NULL) {
  46. throw new \BadMethodCallException('Settings::$instance is not initialized yet. Whatever you are trying to do, it might be too early for that. You could call Settings::initialize(), but it is probably better to wait until it is called in the regular way. Also check for recursions.');
  47. }
  48. return self::$instance;
  49. }
  50. /**
  51. * Protects creating with clone.
  52. */
  53. private function __clone() {
  54. }
  55. /**
  56. * Prevents settings from being serialized.
  57. */
  58. public function __sleep() {
  59. throw new \LogicException('Settings can not be serialized. This probably means you are serializing an object that has an indirect reference to the Settings object. Adjust your code so that is not necessary.');
  60. }
  61. /**
  62. * Returns a setting.
  63. *
  64. * Settings can be set in settings.php in the $settings array and requested
  65. * by this function. Settings should be used over configuration for read-only,
  66. * possibly low bootstrap configuration that is environment specific.
  67. *
  68. * @param string $name
  69. * The name of the setting to return.
  70. * @param mixed $default
  71. * (optional) The default value to use if this setting is not set.
  72. *
  73. * @return mixed
  74. * The value of the setting, the provided default if not set.
  75. */
  76. public static function get($name, $default = NULL) {
  77. if ($name === 'install_profile' && isset(self::$instance->storage[$name])) {
  78. @trigger_error('To access the install profile in Drupal 8 use \Drupal::installProfile() or inject the install_profile container parameter into your service. See https://www.drupal.org/node/2538996', E_USER_DEPRECATED);
  79. }
  80. return isset(self::$instance->storage[$name]) ? self::$instance->storage[$name] : $default;
  81. }
  82. /**
  83. * Returns all the settings. This is only used for testing purposes.
  84. *
  85. * @return array
  86. * All the settings.
  87. */
  88. public static function getAll() {
  89. return self::$instance->storage;
  90. }
  91. /**
  92. * Bootstraps settings.php and the Settings singleton.
  93. *
  94. * @param string $app_root
  95. * The app root.
  96. * @param string $site_path
  97. * The current site path.
  98. * @param \Composer\Autoload\ClassLoader $class_loader
  99. * The class loader that is used for this request. Passed by reference and
  100. * exposed to the local scope of settings.php, so as to allow it to be
  101. * decorated with Symfony's ApcClassLoader, for example.
  102. *
  103. * @see default.settings.php
  104. */
  105. public static function initialize($app_root, $site_path, &$class_loader) {
  106. // Export these settings.php variables to the global namespace.
  107. global $config_directories, $config;
  108. $settings = [];
  109. $config = [];
  110. $databases = [];
  111. if (is_readable($app_root . '/' . $site_path . '/settings.php')) {
  112. require $app_root . '/' . $site_path . '/settings.php';
  113. }
  114. // Initialize Database.
  115. Database::setMultipleConnectionInfo($databases);
  116. // For BC ensure the $config_directories global is set both in the global
  117. // and settings.
  118. if (!isset($settings['config_sync_directory']) && !empty($config_directories['sync'])) {
  119. @trigger_error('$config_directories[\'sync\'] has moved to $settings[\'config_sync_directory\']. See https://www.drupal.org/node/3018145.', E_USER_DEPRECATED);
  120. $settings['config_sync_directory'] = $config_directories['sync'];
  121. }
  122. elseif (isset($settings['config_sync_directory'])) {
  123. $config_directories['sync'] = $settings['config_sync_directory'];
  124. }
  125. // Initialize Settings.
  126. new Settings($settings);
  127. }
  128. /**
  129. * Gets a salt useful for hardening against SQL injection.
  130. *
  131. * @return string
  132. * A salt based on information in settings.php, not in the database.
  133. *
  134. * @throws \RuntimeException
  135. */
  136. public static function getHashSalt() {
  137. $hash_salt = self::$instance->get('hash_salt');
  138. // This should never happen, as it breaks user logins and many other
  139. // services. Therefore, explicitly notify the user (developer) by throwing
  140. // an exception.
  141. if (empty($hash_salt)) {
  142. throw new \RuntimeException('Missing $settings[\'hash_salt\'] in settings.php.');
  143. }
  144. return $hash_salt;
  145. }
  146. /**
  147. * Generates a prefix for APCu user cache keys.
  148. *
  149. * A standardized prefix is useful to allow visual inspection of an APCu user
  150. * cache. By default, this method will produce a unique prefix per site using
  151. * the hash salt. If the setting 'apcu_ensure_unique_prefix' is set to FALSE
  152. * then if the caller does not provide a $site_path only the Drupal root will
  153. * be used. This allows tests to use the same prefix ensuring that the number
  154. * of APCu items created during a full test run is kept to a minimum.
  155. * Additionally, if a multi site implementation does not use site specific
  156. * module directories setting apcu_ensure_unique_prefix would allow the sites
  157. * to share APCu cache items.
  158. *
  159. * @param $identifier
  160. * An identifier for the prefix. For example, 'class_loader' or
  161. * 'cache_backend'.
  162. *
  163. * @return string
  164. * The prefix for APCu user cache keys.
  165. *
  166. * @see https://www.drupal.org/project/drupal/issues/2926309
  167. */
  168. public static function getApcuPrefix($identifier, $root, $site_path = '') {
  169. if (static::get('apcu_ensure_unique_prefix', TRUE)) {
  170. return 'drupal.' . $identifier . '.' . \Drupal::VERSION . '.' . static::get('deployment_identifier') . '.' . hash_hmac('sha256', $identifier, static::get('hash_salt') . '.' . $root . '/' . $site_path);
  171. }
  172. return 'drupal.' . $identifier . '.' . \Drupal::VERSION . '.' . static::get('deployment_identifier') . '.' . Crypt::hashBase64($root . '/' . $site_path);
  173. }
  174. }