diff --git a/core/INSTALL.txt b/core/INSTALL.txt index f985620..080aad1 100644 --- a/core/INSTALL.txt +++ b/core/INSTALL.txt @@ -148,40 +148,39 @@ INSTALLATION b. Missing settings file. Drupal will try to automatically create settings.php and services.yml - files, which are normally in the directory sites/default (to avoid + files, which are normally in the directory settings (to avoid problems when upgrading, Drupal is not packaged with this file). If auto-creation of either file fails, you will need to create the file - yourself. Use the template sites/default/default.settings.php or - sites/default/default.services.yml respectively. + yourself. Use the template core/default.settings.php or + core/default.services.yml respectively. For example, on a Unix/Linux command line, you can make a copy of the default.settings.php and default.services.yml files with the commands: - cp sites/default/default.settings.php sites/default/settings.php - cp sites/default/default.services.yml sites/default/services.yml + cp core/default.settings.php settings/settings.php + cp core/default.services.yml settings/services.yml Next, grant write privileges to the file to everyone (including the web server) with the command: - chmod a+w sites/default/settings.php - chmod a+w sites/default/services.yml + chmod a+w settings/settings.php + chmod a+w settings/services.yml Be sure to set the permissions back after the installation is finished! Sample command: - chmod go-w sites/default/settings.php - chmod go-w sites/default/services.yml + chmod go-w settings/settings.php + chmod go-w settings/services.yml c. Write permissions after install. - The install script will attempt to write-protect the settings.php file and - the sites/default directory after saving your configuration. If this - fails, you will be notified, and you can do it manually. Sample commands - from a Unix/Linux command line: + The install script will attempt to write-protect the settings.php file + after saving your configuration. If this fails, you will be notified, and + you can do it manually. Sample commands from a Unix/Linux command line: - chmod go-w sites/default/settings.php - chmod go-w sites/default/services.yml - chmod go-w sites/default + chmod go-w settings/settings.php + chmod go-w settings/services.yml + chmod go-w settings 4. Verify that the site is working. @@ -298,9 +297,9 @@ Drupal can be reinstalled without downloading and extracting the Drupal release. 1. Drop all the tables in your database. -2. Remove everything in sites/default/files. +2. Remove everything in the files directory. -3. Remove sites/default/settings.php. +3. Remove settings.php. 4. Follow the Installation Instructions above starting from Step 3 (Run the install script). @@ -333,28 +332,28 @@ MULTISITE CONFIGURATION A single Drupal installation can host several Drupal-powered sites, each with its own individual configuration. -For this to work you need the file sites/sites.php to exist. Make a copy of -the example.sites.php file: +For this to work you need to enable the commented out $sites variable in the +settings.php in Drupal's root directory, like so: - $ cp sites/example.sites.php sites/sites.php + $sites = array(); Additional site configurations are created in subdirectories within the 'sites' directory. Each subdirectory must have a 'settings.php' file, which specifies the configuration settings. The easiest way to create additional sites is to -copy file 'default.settings.php' from the 'sites/default' directory into the -new site directory with file name 'settings.php' and modify as appropriate. +copy file 'core/default.settings.php' into the new site directory with file name +'settings.php' and modify as appropriate. + The new directory name is constructed from the site's URL. The configuration for www.example.com could be in 'sites/example.com/settings.php' (note that 'www.' should be omitted if users can access your site at http://example.com/). - $ cp sites/default/defaults.settings.php sites/example.com/settings.php + $ cp core/default.settings.php sites/example.com/settings.php Sites do not have to have a different domain. You can also use subdomains and subdirectories for Drupal sites. For example, example.com, sub.example.com, and sub.example.com/site3 can all be defined as independent Drupal sites. The setup for a configuration such as this would look like the following: - sites/default/settings.php sites/example.com/settings.php sites/sub.example.com/settings.php sites/sub.example.com.site3/settings.php @@ -369,7 +368,7 @@ first configuration it finds: sites/www.sub.example.com/settings.php sites/sub.example.com/settings.php sites/example.com/settings.php - sites/default/settings.php + settings.php If you are installing on a non-standard port, the port number is treated as the deepest subdomain. For example: http://www.example.com:8080/ could be loaded diff --git a/core/UPGRADE.txt b/core/UPGRADE.txt index 420f6ad..a422639 100644 --- a/core/UPGRADE.txt +++ b/core/UPGRADE.txt @@ -61,8 +61,8 @@ following the instructions in the INTRODUCTION section at the top of this file: If you made modifications to files like .htaccess or robots.txt, you will need to re-apply them from your backup, after the new files are in place. - Sometimes an update includes changes to default.settings.php (this will be - noted in the release notes). If that's the case, follow these steps: + Sometimes an update includes changes to core/default.settings.php (this will + be noted in the release notes). If that's the case, follow these steps: - Make a backup copy of your settings.php file, with a different file name. diff --git a/sites/default/default.services.yml b/core/default.services.yml similarity index 100% copy from sites/default/default.services.yml copy to core/default.services.yml diff --git a/sites/default/default.settings.php b/core/default.settings.php similarity index 100% copy from sites/default/default.settings.php copy to core/default.settings.php diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 8c96031..aecd00f 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -13,6 +13,7 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; use Drupal\Core\Utility\Error; use Symfony\Component\ClassLoader\ApcClassLoader; use Symfony\Component\HttpFoundation\Request; @@ -209,43 +210,22 @@ /** * Returns the appropriate configuration directory. * - * @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. - * @param \Symfony\Component\HttpFoundation\Request $request - * (optional) The current request. Defaults to \Drupal::request() or a new - * request created from globals. + * Temporary backwards-compatibility layer for Drush. * - * @return string - * The path of the matching directory.@see default.settings.php + * @deprecated 8.x-dev + * Use \Drupal\Core\Site\Site::getPath() instead. * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - * Use \Drupal\Core\DrupalKernel::getSitePath() instead. If the kernel is - * unavailable or the site path needs to be recalculated then - * Drupal\Core\DrupalKernel::findSitePath() can be used. - */ -function conf_path($require_settings = TRUE, $reset = FALSE, Request $request = NULL) { - if (!isset($request)) { - if (\Drupal::hasRequest()) { - $request = \Drupal::request(); - } - // @todo Remove once external CLI scripts (Drush) are updated. - else { - $request = Request::createFromGlobals(); - } - } - if (\Drupal::hasService('kernel')) { - $site_path = \Drupal::service('kernel')->getSitePath(); - } - if (!isset($site_path) || empty($site_path)) { - $site_path = DrupalKernel::findSitePath($request, $require_settings); + * @internal + */ +function conf_path() { + if (strpos(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[1]['function'], 'drush') === FALSE) { + throw new \Exception('conf_path() is retained for Drush compatibility only.'); } - return $site_path; + // When called from _drush_bootstrap_drupal_site_validate() on testbots, this + // function is supposed to return the site path of the parent site, which is + // '' (the document root). Ensure that the returned path is relative. + // @see https://github.com/drush-ops/drush/blob/master/includes/bootstrap.inc#L782 + return '.'; } /** * Returns the path of a configuration directory. diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 7d23bb9..9080e64 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -16,6 +16,7 @@ use Drupal\Core\Language\LanguageManager; use Drupal\Core\Page\DefaultHtmlPageRenderer; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; use Drupal\Core\StringTranslation\Translator\FileTranslation; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\DependencyInjection\ContainerBuilder; @@ -289,6 +290,12 @@ function install_begin_request(&$install_state) { $class_loader = require __DIR__ . '/../vendor/autoload.php'; Settings::initialize($site_path, $class_loader); + // Initialize the site directory. + // This primes the site path to be used during installation, to allow an empty + // site folder to be prepared in the /sites directory into which Drupal will + // be installed. + Site::initInstaller(DRUPAL_ROOT); + // Ensure that procedural dependencies are loaded as early as possible, // since the error/exception handlers depend on them. require_once __DIR__ . '/../modules/system/system.install'; @@ -370,7 +377,7 @@ function install_begin_request(&$install_state) { $directory = $GLOBALS['config']['locale.settings']['translation.path']; } else { - $directory = $site_path . '/files/translations'; + $directory = Site::getPath('files/translations'); } $container->set('string_translator.file_translation', new FileTranslation($directory)); $container->get('string_translation') @@ -1005,8 +1012,7 @@ function install_verify_completed_task() { function install_verify_database_settings() { if ($database = Database::getConnectionInfo()) { $database = $database['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; } @@ -1017,14 +1023,19 @@ function install_verify_database_settings() { /** * Checks a database connection and returns any errors. */ -function install_database_errors($database, $settings_file) { + +function install_database_errors($database) { $errors = array(); // Check database type. $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::getPath('settings.php'), + '@drupal' => drupal_install_profile_distribution_name(), + '%driver' => $driver, + )); } else { // Run driver specific validation @@ -1733,8 +1744,8 @@ function install_check_translations($install_state) { $readable = FALSE; $writable = FALSE; // @todo: Make this configurable. - $files_directory = conf_path() . '/files'; - $translations_directory = conf_path() . '/files/translations'; + $files_directory = Site::getPath('files'); + $translations_directory = Site::getPath('files/translations'); $translations_directory_exists = FALSE; $translation_available = FALSE; $online = FALSE; @@ -1910,7 +1921,7 @@ function install_check_requirements($install_state) { $writable = FALSE; $conf_path = './' . conf_path(FALSE); $file = $conf_path . "/{$default_file_info['file']}"; - $default_file = "./sites/default/{$default_file_info['file_default']}"; + $default_file = "./core/{$default_file_info['file_default']}"; $exists = FALSE; // Verify that the directory exists. if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { diff --git a/core/includes/install.inc b/core/includes/install.inc index d1c1596..9bb949f 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -11,6 +11,7 @@ use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; /** * Requirement severity -- Informational message only. @@ -195,7 +196,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::getPath('settings.php'); } // Build list of setting names and insert the values into the global namespace. $variable_names = array(); @@ -468,11 +469,11 @@ function drupal_install_config_directories() { $config_directories_hash = Crypt::randomBytesBase64(55); $settings['config_directories'] = array( CONFIG_ACTIVE_DIRECTORY => (object) array( - 'value' => conf_path() . '/files/config_' . $config_directories_hash . '/active', + 'value' => Site::getPath('files/config_' . $config_directories_hash . '/active'), 'required' => TRUE, ), CONFIG_STAGING_DIRECTORY => (object) array( - 'value' => conf_path() . '/files/config_' . $config_directories_hash . '/staging', + 'value' => Site::getPath('files/config_' . $config_directories_hash . '/staging'), 'required' => TRUE, ), ); @@ -680,6 +681,9 @@ function drupal_install_system($install_state) { * * @return * TRUE on success or FALSE on failure. A message is set for the latter. + * + * @todo Do not automatically call into drupal_install_fix_file(). + * @see https://drupal.org/node/1616266 */ function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { $return = TRUE; diff --git a/core/includes/update.inc b/core/includes/update.inc index f9a88db..a8a079b 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -14,6 +14,7 @@ use Drupal\Core\Config\ConfigException; use Drupal\Core\DrupalKernel; use Drupal\Core\Page\DefaultHtmlPageRenderer; +use Drupal\Core\Site\Site; use Drupal\Core\Utility\Error; use Drupal\Component\Uuid\Uuid; use Drupal\Component\Utility\NestedArray; @@ -82,7 +83,7 @@ function update_settings_file_requirements() { $requirements = array(); // Check whether settings.php needs to be rewritten. - $settings_file = conf_path() . '/settings.php'; + $settings_file = Site::getPath('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 97eab54..995f0e6 100644 --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Install/Tasks.php @@ -11,6 +11,7 @@ use Drupal\Core\Database\Driver\sqlite\Connection; use Drupal\Core\Database\DatabaseNotFoundException; use Drupal\Core\Database\Install\Tasks as InstallTasks; +use Drupal\Core\Site\Site; /** * Specifies installation tasks for SQLite databases. @@ -49,7 +50,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) . '/files/.ht.sqlite'; + $default_database = Site::getPath('files/.ht.sqlite'); $form['database']['#default_value'] = empty($database['database']) ? $default_database : $database['database']; return $form; } diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php index f51cbb3..43b31ca 100644 --- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php @@ -9,6 +9,7 @@ use Drupal\Core\Extension\Discovery\RecursiveExtensionFilterIterator; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; /** * Discovers available extensions in the filesystem. @@ -135,8 +136,10 @@ public function scan($type, $include_tests = NULL) { $searchdirs[static::ORIGIN_PARENT_SITE] = $parent_site; } - // Search the site-specific directory. - $searchdirs[static::ORIGIN_SITE] = conf_path(); + // Search the site-specific directory, unless it is the same as ORIGIN_ROOT. + if ('' !== $site_path = Site::getPath()) { + $searchdirs[static::ORIGIN_SITE] = $site_path; + } // Unless an explicit value has been passed, manually check whether we are // in a test environment, in which case test extensions must be included. diff --git a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php index c8fdd19..adbcec4 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php @@ -11,6 +11,7 @@ use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Locale\CountryManagerInterface; +use Drupal\Core\Site\Site; use Drupal\Core\State\StateInterface; use Drupal\user\UserStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -93,8 +94,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { $form['#title'] = $this->t('Configure site'); // Warn about settings.php permissions risk - $settings_dir = conf_path(); - $settings_file = $settings_dir . '/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 @@ -103,8 +102,12 @@ public function buildForm(array $form, FormStateInterface $form_state) { // distract from the message that the Drupal installation has completed // successfully.) $post_params = $this->getRequest()->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'))) { - 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'); + if (empty($post_params) && (!drupal_verify_install_file(Site::getAbsolutePath('settings.php'), FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE) || is_writable(Site::getAbsolutePath()))) { + 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' => Site::getPath() ?: Site::getAbsolutePath(), + '%file' => Site::getPath('settings.php'), + '@handbook_url' => 'http://drupal.org/server-permissions', + )), 'warning'); } $form['#attached']['library'][] = 'system/drupal.system'; diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index 48fadf6..803480e 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -28,9 +28,6 @@ public function getFormId() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { - $conf_path = './' . conf_path(FALSE); - $settings_file = $conf_path . '/settings.php'; - $form['#title'] = $this->t('Database configuration'); $drivers = drupal_get_database_types(); @@ -108,7 +105,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); $form['errors'] = array(); - $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file); return $form; } @@ -127,7 +123,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { $database['driver'] = $driver; $form_state['storage']['database'] = $database; - $errors = install_database_errors($database, $form_state->getValue('settings_file')); + $errors = install_database_errors($database); foreach ($errors as $name => $message) { $form_state->setErrorByName($name, $message); } diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php index def307f..df4602e 100644 --- a/core/lib/Drupal/Core/Site/Settings.php +++ b/core/lib/Drupal/Core/Site/Settings.php @@ -101,9 +101,24 @@ public static function initialize($site_path, &$class_loader) { $config = array(); $databases = array(); - // Make conf_path() available as local variable in settings.php. - if (is_readable(DRUPAL_ROOT . '/' . $site_path . '/settings.php')) { - require DRUPAL_ROOT . '/' . $site_path . '/settings.php'; + // Read the global /settings/settings.php file. + // Allow it to set/override the following variables: + $sites = NULL; + $conf_path = NULL; + // Exclude it for test requests to prevent settings of the test runner from + // leaking into the test environment. + if (!drupal_valid_test_ua() && is_readable(DRUPAL_ROOT . '/settings/settings.php')) { + require DRUPAL_ROOT . '/settings/settings.php'; + } + + // Discover the site directory. + Site::init(DRUPAL_ROOT, $sites, $conf_path); + + // Read settings.php of the actual site, unless it is the root/default site. + // Concatenation is safe here, since $conf_path is known to be not empty. + $conf_path = Site::getPath(); + if ($conf_path !== '' && is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) { + require DRUPAL_ROOT . '/' . $conf_path . '/settings.php'; } // Initialize Database. diff --git a/core/lib/Drupal/Core/Site/Site.php b/core/lib/Drupal/Core/Site/Site.php new file mode 100644 index 0000000..916abd9 --- /dev/null +++ b/core/lib/Drupal/Core/Site/Site.php @@ -0,0 +1,378 @@ +isInstaller()) { + throw new \BadMethodCallException('Site path is initialized already.'); + } + } + else { + new self($root_directory); + } + self::$instance->initializePath($sites, $custom_path); + + // Prevent this method from being called more than once. + if (self::$instance->isInstaller()) { + self::$instance->isInstaller = FALSE; + } + } + + /** + * Initializes the Site singleton in the early installer environment. + * + * Primes the Site singleton with an installer flag, which allows the + * application to be installed into a new and empty site directory, which does + * not contain a settings.php yet. + * + * @param string $root_directory + * The root directory to use for absolute paths; i.e., DRUPAL_ROOT. + * + * @throws \BadMethodCallException + * If the site path is initialized already. + * + * @see install_begin_request() + */ + public static function initInstaller($root_directory) { + if (isset(self::$instance)) { + throw new \BadMethodCallException('Site path is initialized already.'); + } + new self($root_directory); + // Denote that we are operating in the special installer environment. + self::$instance->isInstaller = TRUE; + } + + /** + * Constructs the Site singleton. + * + * @throws \BadMethodCallException + * If the site path is initialized already. + */ + private function __construct($root_directory) { + if (isset(self::$instance)) { + throw new \BadMethodCallException('Site path is initialized already.'); + } + $this->root = $root_directory; + self::$instance = $this; + } + + /** + * Re-initializes (resets) the Site singleton for a test run. + * + * @throws \RuntimeException + * If the site path of the test runner is not initialized yet. + * + * @throws \BadMethodCallException + * If no test is executed currently. + * + * @see \Drupal\simpletest\TestBase::prepareEnvironment() + */ + public static function setUpTest() { + if (!isset(self::$instance)) { + throw new \RuntimeException('No original Site to backup. Missing invocation of Site::init()?'); + } + if (!drupal_valid_test_ua()) { + throw new \BadMethodCallException('Site is not executing a test.'); + } + self::$original = clone self::$instance; + self::$instance = NULL; + } + + /** + * Reverts the Site singleton to the original after a test run. + * + * @throws \RuntimeException + * If there is no test runner site path to revert to. + * + * @throws \BadMethodCallException + * If a test is still being executed currently. + * + * @see \Drupal\simpletest\TestBase::restoreEnvironment() + */ + public static function tearDownTest() { + if (!isset(self::$original)) { + throw new \RuntimeException('No original Site to revert to. Missing invocation of Site::setUpTest()?'); + } + // Do not allow to restore original Site singleton in a test environment, + // unless we are testing the test environment setup and teardown itself. + // @see \Drupal\simpletest\Tests\BrokenSetUpTest + if (drupal_valid_test_ua() && !DRUPAL_TEST_IN_CHILD_SITE) { + throw new \BadMethodCallException('Unable to revert Site: A test is still being executed.'); + } + self::$instance = clone self::$original; + self::$original = NULL; + } + + /** + * Returns whether the Site singleton was instantiated for the installer. + * + * @return bool + */ + private function isInstaller() { + return $this->isInstaller; + } + + /** + * Initializes the site path. + * + * @param array|null $sites + * (optional) A multi-site mapping, as defined in settings.php. + * @param string|null $custom_path + * (optional) An explicit site path to set; skipping site negotiation. + */ + private function initializePath(array $sites = NULL, $custom_path = NULL) { + // Force-override the site directory in tests. + if ($test_prefix = drupal_valid_test_ua()) { + $this->path = 'sites/simpletest/' . substr($test_prefix, 10); + } + // An explicitly defined $conf_path in /settings.php takes precedence. + elseif (isset($custom_path)) { + $this->path = $custom_path; + } + // If the multi-site functionality was enabled in /settings.php, discover + // the path for the current site. + // $sites just needs to be defined; an explicit mapping is not required. + elseif (isset($sites)) { + $this->path = $this->determinePath($sites, !$this->isInstaller()); + } + // Otherwise, the Drupal root directory is the site directory. + else { + $this->path = ''; + } + } + + /** + * Finds the appropriate configuration directory for a given host and path. + * + * Finds a matching configuration directory file by stripping the server + * hostname from left to right and pathname from right to left. + * + * By default, the site directory must contain a 'settings.php' file. If the + * parameter $require_settings is set to FALSE, then a site directory without + * a 'settings.php' file will be valid, too. The first valid site directory + * found will be used and less specific options will be ignored. + * + * The $sites variable can define site directory aliases as an associative + * array. For example, to create a directory alias for + * http://www.drupal.org:8080/mysite/test whose configuration file is in + * sites/example.com, the array should be defined as: + * + * @code + * $sites['8080.www.drupal.org.mysite.test'] = 'example.com'; + * @endcode + * + * @see default.settings.php + * + * @param array $sites + * A multi-site alias mapping, as defined in settings.php. May be empty. + * @param bool $require_settings + * If TRUE, only site directories containing a settings.php file will be + * recognized. During installation, this is set to FALSE, so that Drupal can + * detect a site directory in which to create a new settings.php file. + * + * @return string + * The relative path of the site directory. May be an empty string, in case + * no site-specific directory matched, in which case the root directory is + * the site directory. + */ + private function determinePath(array $sites, $require_settings) { + // The hostname and optional port number, e.g. "www.example.com" or + // "www.example.com:8080". + $http_host = $_SERVER['HTTP_HOST']; + // The part of the URL following the hostname, including the leading slash. + $script_name = $_SERVER['SCRIPT_NAME'] ?: $_SERVER['SCRIPT_FILENAME']; + + $uri = explode('/', $script_name); + $server = explode('.', implode('.', array_reverse(explode(':', rtrim($http_host, '.'))))); + for ($i = count($uri) - 1; $i > 0; $i--) { + for ($j = count($server); $j > 0; $j--) { + $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i)); + // Check for an alias in $sites from settings.php. + if (isset($sites[$dir])) { + $dir = $sites[$dir]; + } + if ($require_settings) { + if (file_exists($this->root . '/sites/' . $dir . '/settings.php')) { + return "sites/$dir"; + } + } + elseif (file_exists($this->root . '/sites/' . $dir)) { + return "sites/$dir"; + } + } + } + return ''; + } + + /** + * Prefixes a given subpathname with the site directory, if any. + * + * Site::getPath() and this helper method only exists to ensure that a given + * subpathname does not result in an absolute filesystem path in case of a + * string concatenation like the following: + * + * @code + * // If the sire directory path is empty (root directory), then the resulting + * // filesystem path would become absolute; i.e.: "/some/file" + * unlink($site_path . '/some/file'); + * @endcode + * + * In case the PHP process has write access to the entire filesystem, such a + * file operation could succeed and potentially affect arbitrary other files + * and directories that happen to exist. That must not happen. + * + * @param string $subpathname + * The subpathname to prefix. + * + * @return string + * The prefixed subpathname. + * + * @throws \RuntimeException + * If the site path is not initialized yet. + */ + private function resolvePath($subpathname) { + // Extra safety protection in case a script somehow manages to bypass all + // other protections. + if (!isset($this->path)) { + throw new \RuntimeException('Site path is not initialized yet.'); + } + // A faulty call to Site::getPath() might include a leading slash (/), in + // which case the entire site path resolution of this function would be + // pointless, because the resulting path would still be absolute. Therefore, + // guarantee that even a bogus argument is resolved correctly. + $subpathname = ltrim($subpathname, '/'); + + if ($this->path !== '') { + if ($subpathname !== '') { + return $this->path . '/' . $subpathname; + } + return $this->path; + } + return $subpathname; + } + + /** + * Returns the given path relative to the site directory. + * + * Use this function instead of appending strings to the site path manually, + * because the site directory may be the root directory and thus a + * concatenated path would result in an absolute filesystem path. + * + * @param string $subpathname + * (optional) A relative subpathname to append to the site path. + * + * @return string + * The given $subpathname, potentially prefixed with the site path. + * + * @throws \RuntimeException + * If the site path is not initialized yet. + * + * @see \Drupal\Core\Site\Site::getAbsolutePath() + */ + public static function getPath($subpathname = '') { + return self::$instance->resolvePath($subpathname); + } + + /** + * Returns the given path relative to the site directory, as an absolute path. + * + * Use this function instead of appending strings to the site path manually, + * because the site directory may be the root directory and thus a + * concatenated path would result in an absolute filesystem path. + * + * @param string $subpathname + * (optional) A relative subpathname to append to the site path. + * + * @return string + * The given $subpathname, potentially prefixed with the site path, as an + * absolute filesystem path. + * + * @throws \RuntimeException + * If the site path is not initialized yet. + * + * @see \Drupal\Core\Site\Site::getPath() + */ + public static function getAbsolutePath($subpathname = '') { + $subpathname = self::$instance->resolvePath($subpathname); + if ($subpathname !== '') { + return self::$instance->root . '/' . $subpathname; + } + else { + return self::$instance->root; + } + } + +} diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php index 637c9ef..45661a7 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php @@ -9,6 +9,7 @@ use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; /** * Defines a Drupal public (public://) stream wrapper class. @@ -40,7 +41,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::getPath('files')); return $base_path; } diff --git a/core/modules/file/tests/file_test/src/DummyReadOnlyStreamWrapper.php b/core/modules/file/tests/file_test/src/DummyReadOnlyStreamWrapper.php index d230bc5..8617566 100644 --- a/core/modules/file/tests/file_test/src/DummyReadOnlyStreamWrapper.php +++ b/core/modules/file/tests/file_test/src/DummyReadOnlyStreamWrapper.php @@ -7,6 +7,7 @@ namespace Drupal\file_test; +use Drupal\Core\Site\Site; use Drupal\Core\StreamWrapper\LocalReadOnlyStream; /** @@ -16,7 +17,7 @@ */ class DummyReadOnlyStreamWrapper extends LocalReadOnlyStream { function getDirectoryPath() { - return conf_path() . '/files'; + return Site::getPath('files'); } /** diff --git a/core/modules/file/tests/file_test/src/DummyStreamWrapper.php b/core/modules/file/tests/file_test/src/DummyStreamWrapper.php index cbea40f..dd919c8 100644 --- a/core/modules/file/tests/file_test/src/DummyStreamWrapper.php +++ b/core/modules/file/tests/file_test/src/DummyStreamWrapper.php @@ -7,6 +7,7 @@ namespace Drupal\file_test; +use Drupal\Core\Site\Site; use Drupal\Core\StreamWrapper\LocalStream; /** @@ -16,7 +17,7 @@ */ class DummyStreamWrapper extends LocalStream { function getDirectoryPath() { - return conf_path() . '/files'; + return Site::getPath('files'); } /** diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 197eded..6604986 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -6,6 +6,7 @@ */ use Drupal\Core\Language\Language; +use Drupal\Core\Site\Site; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected; /** @@ -14,7 +15,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::getPath('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/src/TestBase.php b/core/modules/simpletest/src/TestBase.php index a4cfe98..f144212 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -20,6 +20,7 @@ use Drupal\Core\Session\AccountProxy; use Drupal\Core\Session\AnonymousUserSession; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; use Drupal\Core\StreamWrapper\PublicStream; use Drupal\Core\Utility\Error; use Symfony\Component\HttpFoundation\Request; @@ -1002,7 +1003,7 @@ private function prepareEnvironment() { } // Backup current in-memory configuration. - $this->originalSite = conf_path(); + $this->originalSite = Site::getPath(); $this->originalSettings = Settings::getAll(); $this->originalConfig = $GLOBALS['config']; // @todo Remove all remnants of $GLOBALS['conf']. @@ -1017,7 +1018,7 @@ private 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::getPath('files')); $this->originalProfile = drupal_get_profile(); $this->originalUser = isset($user) ? clone $user : NULL; @@ -1089,8 +1090,11 @@ private function prepareEnvironment() { // After preparing the environment and changing the database prefix, we are // in a valid test environment. + if (!is_dir(DRUPAL_ROOT . '/' . $this->siteDirectory)) { + throw new \RuntimeException("Test site directory '$this->siteDirectory' does not exist."); + } drupal_valid_test_ua($this->databasePrefix); - conf_path(FALSE, TRUE); + Site::setUpTest(); // Reset settings. new Settings(array( @@ -1194,7 +1198,7 @@ private function restoreEnvironment() { else { drupal_valid_test_ua(FALSE); } - conf_path(TRUE, TRUE); + Site::tearDownTest(); // Restore stream wrappers of the test runner. file_get_stream_wrappers(); diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index 8ff3575..8dba66c 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -11,6 +11,7 @@ use Drupal\Component\Serialization\Yaml; use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\Settings; use Drupal\Component\Utility\String; use Drupal\Core\Cache\Cache; use Drupal\Core\DependencyInjection\YamlFileLoader; @@ -781,8 +782,9 @@ protected function setUp() { // installation. // Not using File API; a potential error must trigger a PHP warning. $directory = DRUPAL_ROOT . '/' . $this->siteDirectory; - copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php'); - copy(DRUPAL_ROOT . '/sites/default/default.services.yml', $directory . '/services.yml'); + copy(DRUPAL_ROOT . '/core/default.settings.php', $directory . '/settings.php'); + copy(DRUPAL_ROOT . '/core/default.services.yml', $directory . '/services.yml'); + // All file system paths are created by System module during installation. // @see system_requirements() @@ -801,10 +803,13 @@ protected function setUp() { ); // Add the parent profile's search path to the child site's search paths. // @see \Drupal\Core\Extension\ExtensionDiscovery::getProfileDirectories() - $settings['conf']['simpletest.settings']['parent_profile'] = (object) array( + $settings['config']['simpletest.settings']['parent_profile'] = (object) array( 'value' => $this->originalProfile, 'required' => TRUE, ); + // Write a new settings.php for the test site environment. + // drupal_rewrite_settings() will reload Settings and update + // $GLOBALS['config'] accordingly. $this->writeSettings($settings); // Allow for test-specific overrides. $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php'; @@ -843,7 +848,8 @@ protected function setUp() { // directory has to be writable. // TestBase::restoreEnvironment() will delete the entire site directory. // Not using File API; a potential error must trigger a PHP warning. - chmod($directory, 0777); + chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777); + chmod(DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php', 0666); $request = \Drupal::request(); $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', TRUE); diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php index a7ac85a..ee2c35b 100644 --- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php +++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php @@ -10,6 +10,7 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Site\Settings; use Drupal\simpletest\KernelTestBase; +use Drupal\Core\Site\Site; use Symfony\Component\HttpFoundation\Request; /** @@ -20,6 +21,9 @@ class DrupalKernelTest extends KernelTestBase { protected function setUp() { + // Initialize the test Site singleton, so that Site::getPath() works. + Site::init(DRUPAL_ROOT); + // DrupalKernel relies on global $config_directories and requires those // directories to exist. Therefore, create the directories, but do not // invoke KernelTestBase::setUp(), since that would set up further diff --git a/core/modules/system/src/Tests/File/DirectoryTest.php b/core/modules/system/src/Tests/File/DirectoryTest.php index 158be71..ae36102 100644 --- a/core/modules/system/src/Tests/File/DirectoryTest.php +++ b/core/modules/system/src/Tests/File/DirectoryTest.php @@ -7,6 +7,8 @@ namespace Drupal\system\Tests\File; +use Drupal\Core\Site\Site; + /** * Tests operations dealing with directories. * @@ -17,7 +19,7 @@ class DirectoryTest extends FileTestBase { * Test local directory handling functions. */ function testFileCheckLocalDirectoryHandling() { - $directory = conf_path() . '/files'; + $directory = Site::getPath('files'); // Check a new recursively created local directory for correct file system // permissions. diff --git a/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php b/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php index c9cb68b..958dc3c 100644 --- a/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php +++ b/core/modules/system/src/Tests/File/ReadOnlyStreamWrapperTest.php @@ -7,6 +7,8 @@ namespace Drupal\system\Tests\File; +use Drupal\Core\Site\Site; + /** * Tests the read-only stream wrapper write functions. * @@ -34,7 +36,7 @@ class ReadOnlyStreamWrapperTest extends FileTestBase { function testWriteFunctions() { // Generate a test file $filename = $this->randomMachineName(); - $filepath = conf_path() . '/files/' . $filename; + $filepath = Site::getPath('files/' . $filename); file_put_contents($filepath, $filename); // Generate a read-only stream wrapper instance @@ -77,7 +79,9 @@ function testWriteFunctions() { // Test the mkdir() function by attempting to create a directory. $dirname = $this->randomMachineName(); - $dir = conf_path() . '/files/' . $dirname; + $dir = Site::getPath('files/' . $dirname); + $dirname = $this->randomName(); + $dir = Site::getPath('files/' . $dirname); $readonlydir = $this->scheme . '://' . $dirname; $this->assertFalse(@drupal_mkdir($readonlydir, 0775, 0), 'Unable to create directory with read-only stream wrapper.'); // Create a temporary directory for testing purposes diff --git a/core/modules/system/src/Tests/System/SettingsRewriteTest.php b/core/modules/system/src/Tests/System/SettingsRewriteTest.php index 741f92c..8df6e44 100644 --- a/core/modules/system/src/Tests/System/SettingsRewriteTest.php +++ b/core/modules/system/src/Tests/System/SettingsRewriteTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Site\Settings; use Drupal\simpletest\KernelTestBase; +use Drupal\Core\Site\Site; /** * Tests the drupal_rewrite_settings() function. @@ -99,7 +100,7 @@ function testDrupalRewriteSettings() { ), ); foreach ($tests as $test) { - $filename = Settings::get('file_public_path', conf_path() . '/files') . '/mock_settings.php'; + $filename = Settings::get('file_public_path', Site::getPath('files')) . '/mock_settings.php'; file_put_contents(DRUPAL_ROOT . '/' . $filename, "assertEqual(file_get_contents(DRUPAL_ROOT . '/' . $filename), " '$no_index = true;' ); // Make an empty file. - $filename = Settings::get('file_public_path', conf_path() . '/files') . '/mock_settings.php'; + $filename = Settings::get('file_public_path', Site::getPath('files')) . '/mock_settings.php'; file_put_contents(DRUPAL_ROOT . '/' . $filename, ""); // Write the setting to the file. diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 8e7b534..2795a34 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -11,6 +11,7 @@ use Drupal\Core\Database\Database; use Drupal\Core\Language\Language; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\Site; use Drupal\Core\StreamWrapper\PublicStream; /** @@ -215,14 +216,17 @@ function system_requirements($phase) { // Test configuration files and directory for writability. if ($phase == 'runtime') { $conf_errors = array(); - $conf_path = conf_path(); - if (!drupal_verify_install_file($conf_path, FILE_NOT_WRITABLE, 'dir')) { - $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array('%file' => $conf_path)); + if (is_writable(Site::getAbsolutePath())) { + $conf_errors[] = t("The directory %file is not protected from modifications and poses a security risk. You must change the directory's permissions to be non-writable.", array( + '%file' => Site::getPath() ?: Site::getAbsolutePath(), + )); } foreach (array('settings.php', 'settings.local.php', 'services.yml') as $conf_file) { - $full_path = $conf_path . '/' . $conf_file; + $full_path = Site::getAbsolutePath($conf_file); if (file_exists($full_path) && !drupal_verify_install_file($full_path, FILE_EXIST|FILE_READABLE|FILE_NOT_WRITABLE)) { - $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array('%file' => $full_path)); + $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", array( + '%file' => Site::getPath($conf_file), + )); } } if (!empty($conf_errors)) { @@ -350,7 +354,7 @@ function system_requirements($phase) { else { // If we are installing Drupal, the settings.php file might not exist yet // in the intended site directory, so don't require it. - $directories[] = conf_path(FALSE) . '/files'; + $directories[] = Site::getPath('files'); } if (!empty($GLOBALS['config']['system.file']['path']['private'])) { $directories[] = $GLOBALS['config']['system.file']['path']['private']; @@ -376,7 +380,7 @@ function system_requirements($phase) { $requirements['config directories'] = array( 'title' => t('Configuration directories'), 'value' => t('Not present'), - 'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => conf_path() . '/settings.php')), + 'description' => t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => Site::getPath('settings.php'))), 'severity' => REQUIREMENT_ERROR, ); } diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc index 1faf7fd..c2e921f 100644 --- a/core/modules/update/update.manager.inc +++ b/core/modules/update/update.manager.inc @@ -36,6 +36,7 @@ * root. */ +use Drupal\Core\Site\Site; use Symfony\Component\HttpFoundation\RedirectResponse; /** @@ -304,7 +305,7 @@ function update_manager_local_transfers_allowed() { // the configuration directory to determine if local transfers will be // allowed. $temporary_file = drupal_tempnam('temporary://', 'update_'); - $local_transfers_allowed = fileowner($temporary_file) === fileowner(conf_path()); + $local_transfers_allowed = fileowner($temporary_file) === fileowner(Site::getAbsolutePath()); // Clean up. If this fails, we can ignore it (since this is just a temporary // file anyway). diff --git a/core/themes/seven/css/components/form.css b/core/themes/seven/css/components/form.css index ac80117..fe9af0b 100644 --- a/core/themes/seven/css/components/form.css +++ b/core/themes/seven/css/components/form.css @@ -214,7 +214,7 @@ textarea.form-textarea { } select:focus, select:hover { - background-image: url(../../../../misc/icons/333333/caret-down.svg), + background-image: url(../../../../misc/icons/333333/caret-down.svg"), -webkit-linear-gradient(top, #fcfcfa, #e9e9dd); color: #1a1a1a; } diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml index 280eb43..792d600 100644 --- a/sites/default/default.services.yml +++ b/sites/default/default.services.yml @@ -1,53 +1 @@ -parameters: - twig.config: - # Twig debugging: - # - # When debugging is enabled: - # - The markup of each Twig template is surrounded by HTML comments that - # contain theming information, such as template file name suggestions. - # - Note that this debugging markup will cause automated tests that directly - # check rendered HTML to fail. When running automated tests, 'twig_debug' - # should be set to FALSE. - # - The dump() function can be used in Twig templates to output information - # about template variables. - # - Twig templates are automatically recompiled whenever the source code - # changes (see twig_auto_reload below). - # - # For more information about debugging Twig templates, see - # http://drupal.org/node/1906392. - # - # Not recommended in production environments - # @default false - debug: false - # Twig auto-reload: - # - # Automatically recompile Twig templates whenever the source code changes. - # If you don't provide a value for twig_auto_reload, it will be determined - # based on the value of twig_debug. - # - # Not recommended in production environments - # @default null - auto_reload: null - # Twig cache: - # - # By default, Twig templates will be compiled and stored in the filesystem - # to increase performance. Disabling the Twig cache will recompile the - # templates from source each time they are used. In most cases the - # twig_auto_reload setting above should be enabled rather than disabling the - # Twig cache. - # - # Not recommended in production environments - # @default true - cache: true - factory.keyvalue: - {} - # Default key/value storage service to use. - # @default keyvalue.database - #default: keyvalue.database - # Collection-specific overrides. - #state: keyvalue.database - factory.keyvalue.expirable: - {} - # Default key/value expirable storage service to use. - # @default keyvalue.database.expirable - #default: keyvalue.database.expirable +# diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 3936dcb..b3d9bbc 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -1,641 +1 @@ 'mysql', - * 'database' => 'databasename', - * 'username' => 'username', - * 'password' => 'password', - * 'host' => 'localhost', - * 'port' => 3306, - * 'prefix' => 'myprefix_', - * 'collation' => 'utf8_general_ci', - * ); - * @endcode - * - * The "driver" property indicates what Drupal database driver the - * connection should use. This is usually the same as the name of the - * database type, such as mysql or sqlite, but not always. The other - * properties will vary depending on the driver. For SQLite, you must - * specify a database file name in a directory that is writable by the - * webserver. For most other drivers, you must specify a - * username, password, host, and database name. - * - * Transaction support is enabled by default for all drivers that support it, - * including MySQL. To explicitly disable it, set the 'transactions' key to - * FALSE. - * Note that some configurations of MySQL, such as the MyISAM engine, don't - * support it and will proceed silently even if enabled. If you experience - * transaction related crashes with such configuration, set the 'transactions' - * key to FALSE. - * - * For each database, you may optionally specify multiple "target" databases. - * A target database allows Drupal to try to send certain queries to a - * different database if it can but fall back to the default connection if not. - * That is useful for primary/replica replication, as Drupal may try to connect - * to a replica server when appropriate and if one is not available will simply - * fall back to the single primary server (The terms primary/replica are - * traditionally referred to as master/slave in database server documentation). - * - * The general format for the $databases array is as follows: - * @code - * $databases['default']['default'] = $info_array; - * $databases['default']['replica'][] = $info_array; - * $databases['default']['replica'][] = $info_array; - * $databases['extra']['default'] = $info_array; - * @endcode - * - * In the above example, $info_array is an array of settings described above. - * The first line sets a "default" database that has one primary database - * (the second level default). The second and third lines create an array - * of potential replica databases. Drupal will select one at random for a given - * request as needed. The fourth line creates a new database with a name of - * "extra". - * - * For a single database configuration, the following is sufficient: - * @code - * $databases['default']['default'] = array( - * 'driver' => 'mysql', - * 'database' => 'databasename', - * 'username' => 'username', - * 'password' => 'password', - * 'host' => 'localhost', - * 'prefix' => 'main_', - * 'collation' => 'utf8_general_ci', - * ); - * @endcode - * - * You can optionally set prefixes for some or all database table names - * by using the 'prefix' setting. If a prefix is specified, the table - * name will be prepended with its value. Be sure to use valid database - * characters only, usually alphanumeric and underscore. If no prefixes - * are desired, leave it as an empty string ''. - * - * To have all database names prefixed, set 'prefix' as a string: - * @code - * 'prefix' => 'main_', - * @endcode - * To provide prefixes for specific tables, set 'prefix' as an array. - * The array's keys are the table names and the values are the prefixes. - * The 'default' element is mandatory and holds the prefix for any tables - * not specified elsewhere in the array. Example: - * @code - * 'prefix' => array( - * 'default' => 'main_', - * 'users' => 'shared_', - * 'sessions' => 'shared_', - * 'role' => 'shared_', - * 'authmap' => 'shared_', - * ), - * @endcode - * You can also use a reference to a schema/database as a prefix. This may be - * useful if your Drupal installation exists in a schema that is not the default - * or you want to access several databases from the same code base at the same - * time. - * Example: - * @code - * 'prefix' => array( - * 'default' => 'main.', - * 'users' => 'shared.', - * 'sessions' => 'shared.', - * 'role' => 'shared.', - * 'authmap' => 'shared.', - * ); - * @endcode - * NOTE: MySQL and SQLite's definition of a schema is a database. - * - * Advanced users can add or override initial commands to execute when - * connecting to the database server, as well as PDO connection settings. For - * example, to enable MySQL SELECT queries to exceed the max_join_size system - * variable, and to reduce the database connection timeout to 5 seconds: - * - * @code - * $databases['default']['default'] = array( - * 'init_commands' => array( - * 'big_selects' => 'SET SQL_BIG_SELECTS=1', - * ), - * 'pdo' => array( - * PDO::ATTR_TIMEOUT => 5, - * ), - * ); - * @endcode - * - * WARNING: These defaults are designed for database portability. Changing them - * may cause unexpected behavior, including potential data loss. - * - * @see DatabaseConnection_mysql::__construct - * @see DatabaseConnection_pgsql::__construct - * @see DatabaseConnection_sqlite::__construct - * - * Database configuration format: - * @code - * $databases['default']['default'] = array( - * 'driver' => 'mysql', - * 'database' => 'databasename', - * 'username' => 'username', - * 'password' => 'password', - * 'host' => 'localhost', - * 'prefix' => '', - * ); - * $databases['default']['default'] = array( - * 'driver' => 'pgsql', - * 'database' => 'databasename', - * 'username' => 'username', - * 'password' => 'password', - * 'host' => 'localhost', - * 'prefix' => '', - * ); - * $databases['default']['default'] = array( - * 'driver' => 'sqlite', - * 'database' => '/path/to/databasefilename', - * ); - * @endcode - */ -$databases = array(); - -/** - * Location of the site configuration files. - * - * The $config_directories array specifies the location of file system - * directories used for configuration data. On install, "active" and "staging" - * directories are created for configuration. The staging directory is used for - * configuration imports; the active directory is not used by default, since the - * default storage for active configuration is the database rather than the file - * system (this can be changed; see "Active configuration settings" below). - * - * The default location for the active and staging directories is inside a - * randomly-named directory in the public files path; this setting allows you to - * override these locations. If you use files for the active configuration, you - * can enhance security by putting the active configuration outside your - * document root. - * - * Example: - * @code - * $config_directories = array( - * CONFIG_ACTIVE_DIRECTORY => '/some/directory/outside/webroot', - * CONFIG_STAGING_DIRECTORY => '/another/directory/outside/webroot', - * ); - * @endcode - */ -$config_directories = array(); - -/** - * Settings: - * - * $settings contains environment-specific configuration, such as the files - * directory and reverse proxy address, and temporary configuration, such as - * turning on Twig debugging and security overrides. - * - * @see \Drupal\Core\Site\Settings::get() - */ - -/** - * Salt for one-time login links, cancel links, form tokens, etc. - * - * This variable will be set to a random value by the installer. All one-time - * login links will be invalidated if the value is changed. Note that if your - * site is deployed on a cluster of web servers, you must ensure that this - * variable has the same value on each server. - * - * For enhanced security, you may set this variable to the contents of a file - * outside your document root; you should also ensure that this file is not - * stored with backups of your database. - * - * Example: - * @code - * $settings['hash_salt'] = file_get_contents('/home/example/salt.txt'); - * @endcode - */ -$settings['hash_salt'] = ''; - -/** - * Access control for update.php script. - * - * If you are updating your Drupal installation using the update.php script but - * are not logged in using either an account with the "Administer software - * updates" permission or the site maintenance account (the account that was - * created during installation), you will need to modify the access check - * statement below. Change the FALSE to a TRUE to disable the access check. - * After finishing the upgrade, be sure to open this file again and change the - * TRUE back to a FALSE! - */ -$settings['update_free_access'] = FALSE; - -/** - * External access proxy settings: - * - * If your site must access the Internet via a web proxy then you can enter - * the proxy settings here. Currently only basic authentication is supported - * by using the username and password variables. The proxy_user_agent variable - * can be set to NULL for proxies that require no User-Agent header or to a - * non-empty string for proxies that limit requests to a specific agent. The - * proxy_exceptions variable is an array of host names to be accessed directly, - * not via proxy. - */ -# $settings['proxy_server'] = ''; -# $settings['proxy_port'] = 8080; -# $settings['proxy_username'] = ''; -# $settings['proxy_password'] = ''; -# $settings['proxy_user_agent'] = ''; -# $settings['proxy_exceptions'] = array('127.0.0.1', 'localhost'); - -/** - * Reverse Proxy Configuration: - * - * Reverse proxy servers are often used to enhance the performance - * of heavily visited sites and may also provide other site caching, - * security, or encryption benefits. In an environment where Drupal - * is behind a reverse proxy, the real IP address of the client should - * be determined such that the correct client IP address is available - * to Drupal's logging, statistics, and access management systems. In - * the most simple scenario, the proxy server will add an - * X-Forwarded-For header to the request that contains the client IP - * address. However, HTTP headers are vulnerable to spoofing, where a - * malicious client could bypass restrictions by setting the - * X-Forwarded-For header directly. Therefore, Drupal's proxy - * configuration requires the IP addresses of all remote proxies to be - * specified in $settings['reverse_proxy_addresses'] to work correctly. - * - * Enable this setting to get Drupal to determine the client IP from - * the X-Forwarded-For header (or $settings['reverse_proxy_header'] if set). - * If you are unsure about this setting, do not have a reverse proxy, - * or Drupal operates in a shared hosting environment, this setting - * should remain commented out. - * - * In order for this setting to be used you must specify every possible - * reverse proxy IP address in $settings['reverse_proxy_addresses']. - * If a complete list of reverse proxies is not available in your - * environment (for example, if you use a CDN) you may set the - * $_SERVER['REMOTE_ADDR'] variable directly in settings.php. - * Be aware, however, that it is likely that this would allow IP - * address spoofing unless more advanced precautions are taken. - */ -# $settings['reverse_proxy'] = TRUE; - -/** - * Specify every reverse proxy IP address in your environment. - * This setting is required if $settings['reverse_proxy'] is TRUE. - */ -# $settings['reverse_proxy_addresses'] = array('a.b.c.d', ...); - -/** - * Set this value if your proxy server sends the client IP in a header - * other than X-Forwarded-For. - */ -# $settings['reverse_proxy_header'] = 'HTTP_X_CLUSTER_CLIENT_IP'; - -/** - * Page caching: - * - * By default, Drupal sends a "Vary: Cookie" HTTP header for anonymous page - * views. This tells a HTTP proxy that it may return a page from its local - * cache without contacting the web server, if the user sends the same Cookie - * header as the user who originally requested the cached page. Without "Vary: - * Cookie", authenticated users would also be served the anonymous page from - * the cache. If the site has mostly anonymous users except a few known - * editors/administrators, the Vary header can be omitted. This allows for - * better caching in HTTP proxies (including reverse proxies), i.e. even if - * clients send different cookies, they still get content served from the cache. - * However, authenticated users should access the site directly (i.e. not use an - * HTTP proxy, and bypass the reverse proxy if one is used) in order to avoid - * getting cached pages from the proxy. - */ -# $settings['omit_vary_cookie'] = TRUE; - -/** - * Class Loader. - * - * By default, Composer's ClassLoader is used, which is best for development, as - * it does not break when code is moved in the file system. You can decorate the - * class loader with a cached solution for better performance, which is - * recommended for production sites. - * - * To do so, you may decorate and replace the local $class_loader variable. - * - * For example, to use Symfony's APC class loader, uncomment the code below. - */ -/* -if ($settings['hash_salt']) { - $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader('drupal.' . $settings['hash_salt'], $class_loader); - $class_loader->unregister(); - $apc_loader->register(); - $class_loader = $apc_loader; -} -*/ - -/** - * Authorized file system operations: - * - * The Update Manager module included with Drupal provides a mechanism for - * site administrators to securely install missing updates for the site - * directly through the web user interface. On securely-configured servers, - * the Update manager will require the administrator to provide SSH or FTP - * credentials before allowing the installation to proceed; this allows the - * site to update the new files as the user who owns all the Drupal files, - * instead of as the user the webserver is running as. On servers where the - * webserver user is itself the owner of the Drupal files, the administrator - * will not be prompted for SSH or FTP credentials (note that these server - * setups are common on shared hosting, but are inherently insecure). - * - * Some sites might wish to disable the above functionality, and only update - * the code directly via SSH or FTP themselves. This setting completely - * disables all functionality related to these authorized file operations. - * - * @see http://drupal.org/node/244924 - * - * Remove the leading hash signs to disable. - */ -# $settings['allow_authorize_operations'] = FALSE; - -/** - * Mixed-mode sessions: - * - * Set to TRUE to create both secure and insecure sessions when using HTTPS. - * Defaults to FALSE. - */ -# $settings['mixed_mode_sessions'] = TRUE; - -/** - * Default mode for for directories and files written by Drupal. - * - * Value should be in PHP Octal Notation, with leading zero. - */ -# $settings['file_chmod_directory'] = 0775; -# $settings['file_chmod_file'] = 0664; - -/** - * Public file path: - * - * A local file system path where public files will be stored. This directory - * must exist and be writable by Drupal. This directory must be relative to - * the Drupal installation directory and be accessible over the web. - */ -# $settings['file_public_path'] = 'sites/default/files'; - -/** - * Session write interval: - * - * Set the minimum interval between each session write to database. - * For performance reasons it defaults to 180. - */ -# $settings['session_write_interval'] = 180; - -/** - * String overrides: - * - * To override specific strings on your site with or without enabling the Locale - * module, add an entry to this list. This functionality allows you to change - * a small number of your site's default English language interface strings. - * - * Remove the leading hash signs to enable. - * - * The "en" part of the variable name, is dynamic and can be any langcode of - * any added language. (eg locale_custom_strings_de for german). - */ -# $settings['locale_custom_strings_en'][''] = array( -# 'forum' => 'Discussion board', -# '@count min' => '@count minutes', -# ); - -/** - * A custom theme for the offline page: - * - * This applies when the site is explicitly set to maintenance mode through the - * administration page or when the database is inactive due to an error. - * The template file should also be copied into the theme. It is located inside - * 'core/modules/system/templates/maintenance-page.html.twig'. - * - * Note: This setting does not apply to installation and update pages. - */ -# $settings['maintenance_theme'] = 'bartik'; - -/** - * Base URL (optional). - * - * If Drupal is generating incorrect URLs on your site, which could - * be in HTML headers (links to CSS and JS files) or visible links on pages - * (such as in menus), uncomment the Base URL statement below (remove the - * leading hash sign) and fill in the absolute URL to your Drupal installation. - * - * You might also want to force users to use a given domain. - * See the .htaccess file for more information. - * - * Examples: - * $base_url = 'http://www.example.com'; - * $base_url = 'http://www.example.com:8888'; - * $base_url = 'http://www.example.com/drupal'; - * $base_url = 'https://www.example.com:8888/drupal'; - * - * It is not allowed to have a trailing slash; Drupal will add it - * for you. - */ -# $base_url = 'http://www.example.com'; // NO trailing slash! - -/** - * PHP settings: - * - * To see what PHP settings are possible, including whether they can be set at - * runtime (by using ini_set()), read the PHP documentation: - * http://php.net/manual/ini.list.php - * See \Drupal\Core\DrupalKernel::bootEnvironment() for required runtime - * settings and the .htaccess file for non-runtime settings. - * Settings defined there should not be duplicated here so as to avoid conflict - * issues. - */ - -/** - * Some distributions of Linux (most notably Debian) ship their PHP - * installations with garbage collection (gc) disabled. Since Drupal depends on - * PHP's garbage collection for clearing sessions, ensure that garbage - * collection occurs by using the most common settings. - */ -ini_set('session.gc_probability', 1); -ini_set('session.gc_divisor', 100); - -/** - * Set session lifetime (in seconds), i.e. the time from the user's last visit - * to the active session may be deleted by the session garbage collector. When - * a session is deleted, authenticated users are logged out, and the contents - * of the user's $_SESSION variable is discarded. - */ -ini_set('session.gc_maxlifetime', 200000); - -/** - * Set session cookie lifetime (in seconds), i.e. the time from the session is - * created to the cookie expires, i.e. when the browser is expected to discard - * the cookie. The value 0 means "until the browser is closed". - */ -ini_set('session.cookie_lifetime', 2000000); - -/** - * If you encounter a situation where users post a large amount of text, and - * the result is stripped out upon viewing but can still be edited, Drupal's - * output filter may not have sufficient memory to process it. If you - * experience this issue, you may wish to uncomment the following two lines - * and increase the limits of these variables. For more information, see - * http://php.net/manual/pcre.configuration.php. - */ -# ini_set('pcre.backtrack_limit', 200000); -# ini_set('pcre.recursion_limit', 200000); - -/** - * Drupal automatically generates a unique session cookie name for each site - * based on its full domain name. If you have multiple domains pointing at the - * same Drupal site, you can either redirect them all to a single domain (see - * comment in .htaccess), or uncomment the line below and specify their shared - * base domain. Doing so assures that users remain logged in as they cross - * between your various domains. Make sure to always start the $cookie_domain - * with a leading dot, as per RFC 2109. - */ -# $cookie_domain = '.example.com'; - -/** - * Active configuration settings. - * - * By default, the active configuration is stored in the database in the - * {config} table. To use a different storage mechanism for the active - * configuration, do the following prior to installing: - * - Override the 'bootstrap_config_storage' setting here. It must be set to a - * callable that returns an object that implements - * \Drupal\Core\Config\StorageInterface. - * - Override the service definition 'config.storage.active'. Put this - * override in a services.yml file in the same directory as settings.php - * (definitions in this file will override service definition defaults). - */ -# $settings['bootstrap_config_storage'] = array('Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage'); - -/** - * Configuration overrides. - * - * To globally override specific configuration values for this site, - * set them here. You usually don't need to use this feature. This is - * useful in a configuration file for a vhost or directory, rather than - * the default settings.php. - * - * Note that any values you provide in these variable overrides will not be - * modifiable from the Drupal administration interface. - */ -# $config['system.site']['name'] = 'My Drupal site'; -# $config['system.theme']['default'] = 'stark'; -# $config['user.settings']['anonymous'] = 'Visitor'; - -/** - * CSS/JS aggregated file gzip compression: - * - * By default, when CSS or JS aggregation and clean URLs are enabled Drupal will - * store a gzip compressed (.gz) copy of the aggregated files. If this file is - * available then rewrite rules in the default .htaccess file will serve these - * files to browsers that accept gzip encoded content. This allows pages to load - * faster for these users and has minimal impact on server load. If you are - * using a webserver other than Apache httpd, or a caching reverse proxy that is - * configured to cache and compress these files itself you may want to uncomment - * one or both of the below lines, which will prevent gzip files being stored. - */ -# $config['system.performance']['css']['gzip'] = FALSE; -# $config['system.performance']['js']['gzip'] = FALSE; - -/** - * Fast 404 pages: - * - * Drupal can generate fully themed 404 pages. However, some of these responses - * are for images or other resource files that are not displayed to the user. - * This can waste bandwidth, and also generate server load. - * - * The options below return a simple, fast 404 page for URLs matching a - * specific pattern: - * - $conf['system.performance]['fast_404']['exclude_paths']: A regular - * expression to match paths to exclude, such as images generated by image - * styles, or dynamically-resized images. If you need to add more paths, you - * can add '|path' to the expression. - * - $conf['system.performance]['fast_404']['paths']: A regular expression to - * match paths that should return a simple 404 page, rather than the fully - * themed 404 page. If you don't have any aliases ending in htm or html you - * can add '|s?html?' to the expression. - * - $conf['system.performance]['fast_404']['html']: The html to return for - * simple 404 pages. - * - * Remove the leading hash signs if you would like to alter this functionality. - */ -# $config['system.performance']['fast_404']['exclude_paths'] = '/\/(?:styles)\//'; -# $config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i'; -# $config['system.performance']['fast_404']['html'] = '404 Not Found

Not Found

The requested URL "@path" was not found on this server.

'; - -/** - * Load local development override configuration, if available. - * - * Use settings.local.php to override variables on secondary (staging, - * development, etc) installations of this site. Typically used to disable - * caching, JavaScript/CSS compression, re-routing of outgoing emails, and - * other things that should not happen on development and testing sites. - * - * Keep this code block at the end of this file to take full effect. - */ -# if (file_exists(__DIR__ . '/settings.local.php')) { -# include __DIR__ . '/settings.local.php'; -# } diff --git a/sites/example.sites.php b/sites/example.sites.php deleted file mode 100644 index 2a813dd..0000000 --- a/sites/example.sites.php +++ /dev/null @@ -1,55 +0,0 @@ -..' => '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 - * $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 - * 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 - * for more information on setting up domains, subdomains, and subdirectories. - * - * The following examples look for a site configuration in sites/example.com: - * @code - * URL: http://dev.drupal.org - * $sites['dev.drupal.org'] = 'example.com'; - * - * URL: http://localhost/example - * $sites['localhost.example'] = 'example.com'; - * - * URL: http://localhost:8080/example - * $sites['8080.localhost.example'] = 'example.com'; - * - * 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 - */