diff --git a/core/default.settings.php b/core/default.settings.php index 0181dbc..23ec5bc 100644 --- a/core/default.settings.php +++ b/core/default.settings.php @@ -45,8 +45,6 @@ * hostname with that number. For example, * http://www.drupal.org:8080/mysite/test/ could be loaded from * sites/8080.www.drupal.org.mysite.test/. - * - * @see conf_path() */ /** @@ -66,16 +64,16 @@ * the database (files, system table, etc.) this will ensure the paths are * correct when the site is deployed to a live server. * - * Aliases are defined in an associative array in the format: + * Aliases are defined in an associative array named $sites. The array is + * written in the format: '..' => 'directory'. As an + * example, to map http://www.drupal.org:8080/mysite/test to the configuration + * directory sites/example.com, the array should be defined as: * @code - * '..' => 'directory', - * @endcode - * For example, to map http://www.drupal.org:8080/mysite/test to the directory - * sites/example.com, the array should be defined as: - * @code - * $sites['8080.www.drupal.org.mysite.test'] = 'example.com'; + * $sites = array( + * '8080.www.drupal.org.mysite.test' => 'example.com', + * ); * @endcode - * The URL http://www.drupal.org:8080/mysite/test/ could be a symbolic link or + * The URL, http://www.drupal.org:8080/mysite/test/, could be a symbolic link or * an Apache Alias directive that points to the Drupal root containing * index.php. An alias could also be created for a subdomain. See the * @link http://drupal.org/documentation/install online Drupal installation guide @endlink @@ -83,16 +81,21 @@ * * The following examples look for a site configuration in sites/example.com: * @code - * # URL: http://dev.drupal.org + * URL: http://dev.drupal.org * $sites['dev.drupal.org'] = 'example.com'; - * # URL: http://localhost/example + * + * URL: http://localhost/example * $sites['localhost.example'] = 'example.com'; - * # URL: http://localhost:8080/example + * + * URL: http://localhost:8080/example * $sites['8080.localhost.example'] = 'example.com'; - * # URL: http://www.drupal.org:8080/mysite/test/ + * + * URL: http://www.drupal.org:8080/mysite/test/ * $sites['8080.www.drupal.org.mysite.test'] = 'example.com'; * @endcode * + * @see default.settings.php + * @see conf_path() * @see http://drupal.org/documentation/install/multi-site */ # $sites = array(); diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 98f8c6a..f41807b 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -256,6 +256,11 @@ function timer_stop($name) { * * @param string $custom_path * (optional) A custom $conf_path to set and statically cache. + * @param bool $require_settings + * Only configuration directories with an existing settings.php file + * will be recognized. Defaults to TRUE. During initial installation, + * this is set to FALSE so that Drupal can detect a matching directory, + * then create a new settings.php file in it. * @param bool $reset * Force a full search for matching directories even if one had been * found previously. Defaults to FALSE. @@ -265,11 +270,18 @@ function timer_stop($name) { * * @see default.settings.php */ -function conf_path($custom_path = NULL, $reset = FALSE) { +function conf_path($custom_path = NULL, $require_settings = TRUE, $reset = FALSE) { static $conf_path; global $sites; - if (!empty($custom_path) && is_string($custom_path)) { + if (isset($conf_path) && !$reset) { + return $conf_path; + } + + if (isset($custom_path)) { + if (!is_string($custom_path)) { + throw new \InvalidArgumentException('The first argument to conf_path() must be a string.'); + } $conf_path = $custom_path; return $conf_path; } @@ -291,19 +303,12 @@ function conf_path($custom_path = NULL, $reset = FALSE) { if (!$script_name) { $script_name = $_SERVER['SCRIPT_FILENAME']; } - $require_settings = (bool) $custom_path; $conf_path = find_conf_path($http_host, $script_name, $require_settings, $sites); } // If the multi-site functionality is not enabled, $conf_path is empty, which // means that the root/top-level directory is the site directory. else { - // Many callers of this function append a slash to the returned path and do - // not prefix it with DRUPAL_ROOT, so Drupal writes new files and - // directories to the filesystem's root directory (which is possible on - // unsecured local Windows development environments). We therefore need to - // return a dot instead of an empty string to ensure that the path is - // interpreted as a relative path. - $conf_path = '.'; + $conf_path = ''; } return $conf_path; } @@ -411,6 +416,17 @@ function find_conf_path($http_host, $script_name, $require_settings = TRUE, arra return 'sites/default'; } +function site_path($file_path, $absolute = FALSE) { + $conf_path = conf_path(); + if ($file_path[0] === '/') { + $file_path = substr($file_path, 1); + } + if ($conf_path !== '') { + $file_path = $conf_path . '/' . $file_path; + } + return $absolute ? DRUPAL_ROOT . '/' . $file_path : $file_path; +} + /** * Returns the path of a configuration directory. * @@ -584,25 +600,24 @@ function drupal_settings_initialize($require_settings = TRUE) { // Export these settings.php variables to the global namespace. global $sites, $databases, $cookie_domain, $conf, $db_prefix, $drupal_hash_salt, $base_secure_url, $base_insecure_url, $config_directories; $conf = array(); - // Include the global settings.php to determine whether the multi-site - // functionality is enabled. If settings.php is not required, then the caller - // is likely the installer, in which case the global settings.php may be used - // to enable the multi-site functionality to install Drupal into a - // site-specific directory. + + // Include settings.php to determine whether multi-site functionality is + // enabled. In the installer, $require_settings is FALSE, in which case the + // global settings.php may be used to enable the multi-site functionality + // to install Drupal into a site-specific directory. if ($require_settings || is_readable(DRUPAL_ROOT . '/settings.php')) { require_once DRUPAL_ROOT . '/settings.php'; } // Discover the site directory, priming the static cache in conf_path(). // Make conf_path() available as local variable in settings.php. - $conf_path = conf_path(isset($conf_path) ? $conf_path : $require_settings); + $conf_path = conf_path(isset($conf_path) ? $conf_path : NULL, $require_settings); if (isset($sites) && $conf_path !== '.' && is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) { include_once DRUPAL_ROOT . '/' . $conf_path . '/settings.php'; } require_once __DIR__ . '../../lib/Drupal/Component/Utility/Settings.php'; new Settings(isset($settings) ? $settings : array()); - $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; if (isset($base_url)) { @@ -1996,11 +2011,7 @@ function _drupal_bootstrap_configuration() { // Load the procedural configuration system helper functions. require_once __DIR__ . '/config.inc'; - // Set the Drupal custom error handler. - // Circular dependency: The error/exception handler requires config, which - // requires the service container, which requires the class loader, which - // requires $conf/settings.php (to be swappable). Therefore, errors in early - // bootstrap and settings.php cannot be handled by Drupal. + // Set the Drupal custom error handler. (requires \Drupal::config()) set_error_handler('_drupal_error_handler'); set_exception_handler('_drupal_exception_handler'); @@ -2300,12 +2311,13 @@ function _drupal_load_test_overrides($test_prefix) { } // Check for and load a settings.php file in the simpletest files directory. - $filename = conf_path() . '/files/' . $path_prefix . '/settings.php'; + $filename = DRUPAL_ROOT . '/' . conf_path() . '/files/' . $path_prefix . '/settings.php'; if (file_exists($filename)) { $settings = settings()->getAll(); - $conf_path = &drupal_static('conf_path'); + $conf_path = conf_path(); // This can override $conf, $conf_path, $settings, and $config_directories. include $filename; + conf_path($conf_path); // Keep the overriden $conf_path alive across drupal_static_reset() calls. // @see conf_path() $settings['simpletest_conf_path'] = $conf_path; diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index a872e20..7a8f650 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -284,11 +284,8 @@ function install_begin_request(&$install_state) { } // Perform a minimal bootstrap. - // This essentially calls _drupal_bootstrap_configuration(), which in turn - // calls drupal_settings_initialize() using the return value of - // drupal_installation_attempted() as argument. During installation, this - // causes drupal_settings_initialize() to not attempt to load any settings.php - // files, which allows to prime the site path to be used during installation. + // During installation, drupal_settings_initialize() will not attempt to load + // settings.php, so as to prime the site path to be used during installation. // By not requiring settings.php, a bare site folder can be prepared in the // /sites directory, which will be used for installing Drupal. drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); @@ -1082,8 +1079,7 @@ function install_verify_database_settings() { global $databases; if (!empty($databases)) { $database = $databases['default']['default']; - $settings_file = './' . conf_path(FALSE) . '/settings.php'; - $errors = install_database_errors($database, $settings_file); + $errors = install_database_errors($database); if (empty($errors)) { return TRUE; } @@ -1104,8 +1100,6 @@ function install_verify_database_settings() { function install_settings_form($form, &$form_state, &$install_state) { global $databases; - $conf_path = './' . conf_path(FALSE); - $settings_file = $conf_path . '/settings.php'; $database = isset($databases['default']['default']) ? $databases['default']['default'] : array(); drupal_set_title(t('Database configuration')); @@ -1152,7 +1146,6 @@ function install_settings_form($form, &$form_state, &$install_state) { ); $form['errors'] = array(); - $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file); return $form; } @@ -1186,7 +1179,7 @@ function install_settings_form_validate($form, &$form_state) { unset($database['db_prefix']); $form_state['storage']['database'] = $database; - $errors = install_database_errors($database, $form_state['values']['settings_file']); + $errors = install_database_errors($database); foreach ($errors as $name => $message) { form_set_error($name, $form_state, $message); } @@ -1195,7 +1188,7 @@ function install_settings_form_validate($form, &$form_state) { /** * Checks a database connection and returns any errors. */ -function install_database_errors($database, $settings_file) { +function install_database_errors($database) { global $databases; $errors = array(); @@ -1203,7 +1196,11 @@ function install_database_errors($database, $settings_file) { $database_types = drupal_get_database_types(); $driver = $database['driver']; if (!isset($database_types[$driver])) { - $errors['driver'] = t("In your %settings_file file you have configured @drupal to use a %driver server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_distribution_name(), '%driver' => $driver)); + $errors['driver'] = t("In your %settings_file file you have configured @drupal to use a %driver server, however your PHP installation currently does not support this database type.", array( + '%settings_file' => site_path('settings.php'), + '@drupal' => drupal_install_profile_distribution_name(), + '%driver' => $driver, + )); } else { // Run driver specific validation @@ -1501,7 +1498,7 @@ function install_translations_directory() { $directory = $GLOBALS['conf']['locale.settings']['translation.path']; } else { - $directory = conf_path(FALSE) . '/files/translations'; + $directory = site_path('files/translations'); } return $directory; } @@ -2084,7 +2081,7 @@ function install_configure_form($form, &$form_state, &$install_state) { // Warn about settings.php permissions risk $settings_dir = conf_path(); - $settings_file = $settings_dir . '/settings.php'; + $settings_file = site_path('settings.php'); // Check that $_POST is empty so we only show this message when the form is // first displayed, not on the next page after it is submitted. (We do not // want to repeat it multiple times because it is a general warning that is @@ -2093,7 +2090,7 @@ function install_configure_form($form, &$form_state, &$install_state) { // distract from the message that the Drupal installation has completed // successfully.) $post_params = \Drupal::request()->request->all(); - if (empty($post_params) && (!drupal_verify_install_file(DRUPAL_ROOT . '/' . $settings_file, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file(DRUPAL_ROOT . '/' . $settings_dir, FILE_NOT_WRITABLE, 'dir'))) { + if (empty($post_params) && (!drupal_verify_install_file(site_path('settings.php', TRUE), FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || !drupal_verify_install_file(site_path('', TRUE), FILE_NOT_WRITABLE, 'dir'))) { drupal_set_message(t('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, consult the online handbook.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/server-permissions')), 'warning'); } @@ -2239,8 +2236,8 @@ function install_check_translations($install_state) { $readable = FALSE; $writable = FALSE; // @todo: Make this configurable. - $files_directory = conf_path(FALSE) . '/files'; - $translations_directory = conf_path(FALSE) . '/files/translations'; + $files_directory = site_path('files'); + $translations_directory = site_path('files/translations'); $translations_directory_exists = FALSE; $translation_available = FALSE; $online = FALSE; @@ -2393,8 +2390,8 @@ function install_check_requirements($install_state) { if (!$install_state['settings_verified']) { $readable = FALSE; $writable = FALSE; - $conf_path = './' . conf_path(FALSE); - $settings_file = $conf_path . '/settings.php'; + $conf_path = site_path('', TRUE); + $settings_file = site_path('settings.php'); $default_settings_file = './core/default.settings.php'; $file = $conf_path; $exists = FALSE; diff --git a/core/includes/install.inc b/core/includes/install.inc index 256c79e..35d245b 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -195,7 +195,7 @@ function drupal_get_database_types() { */ function drupal_rewrite_settings($settings = array(), $settings_file = NULL) { if (!isset($settings_file)) { - $settings_file = conf_path(FALSE) . '/settings.php'; + $settings_file = site_path('settings.php'); } // Build list of setting names and insert the values into the global namespace. $variable_names = array(); @@ -449,11 +449,11 @@ function drupal_install_config_directories($mode = NULL) { $config_directories_hash = Crypt::randomStringHashed(55); $settings['config_directories'] = array( CONFIG_ACTIVE_DIRECTORY => (object) array( - 'value' => conf_path() . '/files/config_' . $config_directories_hash . '/active', + 'value' => site_path('files/config_' . $config_directories_hash . '/active'), 'required' => TRUE, ), CONFIG_STAGING_DIRECTORY => (object) array( - 'value' => conf_path() . '/files/config_' . $config_directories_hash . '/staging', + 'value' => site_path('files/config_' . $config_directories_hash . '/staging'), 'required' => TRUE, ), ); diff --git a/core/includes/update.inc b/core/includes/update.inc index 24f6583..7f97de0 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -124,7 +124,7 @@ function update_prepare_d8_bootstrap() { // If any of the required settings needs to be written, then settings.php // needs to be writable. if (!$settings_exist) { - $settings_file = conf_path() . '/settings.php'; + $settings_file = site_path('settings.php'); $writable = drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_WRITABLE); $requirements['settings file']['title'] = 'Settings file'; if ($writable) { diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php index 633edc6..8b972f2 100644 --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php @@ -49,7 +49,7 @@ public function getFormOptions(array $database) { // Make the text more accurate for SQLite. $form['database']['#title'] = t('Database file'); $form['database']['#description'] = t('The absolute path to the file where @drupal data will be stored. This must be writable by the web server and should exist outside of the web root.', array('@drupal' => drupal_install_profile_distribution_name())); - $default_database = conf_path(FALSE, TRUE) . '/files/.ht.sqlite'; + $default_database = site_path('files/.ht.sqlite'); $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database']; return $form; } diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php index 90f17b3..6fb15a8 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php @@ -37,7 +37,7 @@ public function getExternalUrl() { * The base path for public:// typically sites/default/files. */ public static function basePath() { - $base_path = settings()->get('file_public_path', conf_path() . '/files'); + $base_path = settings()->get('file_public_path', site_path('files')); if ($test_prefix = drupal_valid_test_ua()) { // Append the testing suffix unless already given. // @see \Drupal\simpletest\WebTestBase::setUp() diff --git a/core/lib/Drupal/Core/SystemListing.php b/core/lib/Drupal/Core/SystemListing.php index 20d95cb..676b994 100644 --- a/core/lib/Drupal/Core/SystemListing.php +++ b/core/lib/Drupal/Core/SystemListing.php @@ -85,7 +85,6 @@ function scan($mask, $directory, $key = 'name') { if (!in_array($key, array('uri', 'filename', 'name'))) { $key = 'uri'; } - $config = conf_path(); // Search for the directory in core. $searchdir = array('core/' . $directory); @@ -100,9 +99,13 @@ function scan($mask, $directory, $key = 'name') { $searchdir[] = $directory; $searchdir[] = 'sites/all/' . $directory; - if (file_exists("$config/$directory")) { - $searchdir[] = "$config/$directory"; + if (conf_path() !== '') { + $site_path = site_path($directory); + if (file_exists($site_path)) { + $searchdir[] = $site_path; + } } + // @todo Find a way to skip ./config directories (but not modules/config). $nomask = '/^(CVS|lib|templates|css|js)$/'; $files = array(); diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 960381c..a3e494e 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -13,7 +13,7 @@ function locale_install() { // Create the interface translations directory and ensure it's writable. if (!$directory = \Drupal::config('locale.settings')->get('translation.path')) { - $directory = conf_path() . '/files/translations'; + $directory = site_path('files/translations'); \Drupal::config('locale.settings')->set('translation.path', $directory)->save(); } file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 560afb1..d90b32a 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -925,7 +925,7 @@ protected function prepareEnvironment() { // Save further contextual information. // Use the original files directory to avoid nesting it within an existing // simpletest directory if a test is executed within a test. - $this->originalFileDirectory = settings()->get('file_public_path', conf_path() . '/files'); + $this->originalFileDirectory = settings()->get('file_public_path', site_path('files')); $this->originalProfile = drupal_get_profile(); $this->originalUser = isset($user) ? clone $user : NULL; @@ -1013,7 +1013,7 @@ protected function prepareConfigDirectories() { include_once DRUPAL_ROOT . '/core/includes/install.inc'; foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) { // Assign the relative path to the global variable. - $path = conf_path() . '/files/simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type; + $path = site_path('files/simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type); $GLOBALS['config_directories'][$type] = $path; // Ensure the directory can be created and is writeable. if (!install_ensure_config_directory($type)) {