diff --git a/core/INSTALL.txt b/core/INSTALL.txt index 1880473..e906f2a 100644 --- a/core/INSTALL.txt +++ b/core/INSTALL.txt @@ -147,26 +147,30 @@ INSTALLATION b. Missing settings file. - Drupal will try to automatically create a settings.php configuration file, - which is normally in the directory sites/default (to avoid problems when - upgrading, Drupal is not packaged with this file). If auto-creation fails, - you will need to create this file yourself, using the file - sites/default/default.settings.php as a template. + Drupal will try to automatically create a settings.php/services.yml + configuration file, which is normally in the directory sites/default (to + avoid problems when upgrading, Drupal is not packaged with this file). If + auto-creation fails, you will need to create this file yourself, using the + files sites/default/default.settings.php and + sites/default/default.services.yml as a template. For example, on a Unix/Linux command line, you can make a copy of the - default.settings.php file with the command: + 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 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 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 c. Write permissions after install. @@ -176,6 +180,7 @@ INSTALLATION 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 4. Verify that the site is working. diff --git a/core/core.services.yml b/core/core.services.yml index 6ff5dd5..8ea2e90 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1,3 +1,9 @@ +parameters: + twig.config: {} + factory.keyvalue: + default: keyvalue.database + factory.keyvalue.expirable: + default: keyvalue.expirable.database services: cache_factory: class: Drupal\Core\Cache\CacheFactory @@ -156,13 +162,13 @@ services: arguments: ['@request_stack', '@url_generator'] keyvalue: class: Drupal\Core\KeyValueStore\KeyValueFactory - arguments: ['@service_container', '@settings'] + arguments: ['@service_container', '%factory.keyvalue%'] keyvalue.database: class: Drupal\Core\KeyValueStore\KeyValueDatabaseFactory arguments: ['@serialization.phpserialize', '@database'] keyvalue.expirable: class: Drupal\Core\KeyValueStore\KeyValueExpirableFactory - arguments: ['@service_container', '@settings'] + arguments: ['@service_container', '%factory.keyvalue.expirable%'] keyvalue.expirable.database: class: Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory arguments: ['@serialization.phpserialize', '@database'] @@ -906,6 +912,28 @@ services: arguments: ['@module_handler'] info_parser: class: Drupal\Core\Extension\InfoParser + twig: + class: Drupal\Core\Template\TwigEnvironment + arguments: ['@twig.loader', '@module_handler', '@theme_handler', '%twig.config%'] + tags: + - { name: service_collector, tag: 'twig.extension', call: addExtension } + twig.extension: + class: Drupal\Core\Template\TwigExtension + tags: + - { name: twig.extension, priority: 100 } + calls: + - [setGenerators, ['@url_generator']] + # @todo Figure out what to do about debugging functions. + # @see http://drupal.org/node/1804998 + twig.extension.debug: + class: Twig_Extension_Debug + tags: + - { name: twig.extension } + twig.loader: + alias: twig.loader.filesystem + twig.loader.filesystem: + class: Twig_Loader_Filesystem + arguments: ['%app.root%'] element_info: class: Drupal\Core\Render\ElementInfo arguments: ['@module_handler'] diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 5dee15d..b3cfbb7 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1887,128 +1887,168 @@ function install_check_requirements($install_state) { // Check the profile requirements. $requirements = drupal_check_profile($profile, $install_state); - // If Drupal is not set up already, we need to create a settings file. - if (!$install_state['settings_verified']) { - $readable = FALSE; - $writable = FALSE; - $conf_path = './' . conf_path(FALSE); - $settings_file = $conf_path . '/settings.php'; - $default_settings_file = './sites/default/default.settings.php'; - $file = $conf_path; - $exists = FALSE; - // Verify that the directory exists. - if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { - // Check if a settings.php file already exists. - $file = $settings_file; - if (drupal_verify_install_file($settings_file, FILE_EXIST)) { - // If it does, make sure it is writable. - $readable = drupal_verify_install_file($settings_file, FILE_READABLE); - $writable = drupal_verify_install_file($settings_file, FILE_WRITABLE); - $exists = TRUE; - } - } + $default_files = array(); + $default_files['settings.php'] = array( + 'file' => 'settings.php', + 'file_default' => 'default.settings.php', + 'title_default' => t('Default settings file'), + 'description_default' => t('The default settings file does not exist.'), + 'title' => t('Settings file'), + ); + $default_files['services.yml'] = array( + 'file' => 'services.yml', + 'file_default' => 'default.services.yml', + 'title_default' => t('Default services file'), + 'description_default' => t('The default services file does not exist.'), + 'title' => t('Services file'), + ); - // If default.settings.php does not exist, or is not readable, throw an - // error. - if (!drupal_verify_install_file($default_settings_file, FILE_EXIST|FILE_READABLE)) { - $requirements['default settings file exists'] = array( - 'title' => t('Default settings file'), - 'value' => t('The default settings file does not exist.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => t('The @drupal installer requires that the %default-file file not be modified in any way from the original download.', array('@drupal' => drupal_install_profile_distribution_name(), '%default-file' => $default_settings_file)), - ); - } - // Otherwise, if settings.php does not exist yet, we can try to copy - // default.settings.php to create it. - elseif (!$exists) { - $copied = drupal_verify_install_file($conf_path, FILE_EXIST|FILE_WRITABLE, 'dir') && @copy($default_settings_file, $settings_file); - if ($copied) { - // If the new settings file has the same owner as default.settings.php, - // this means default.settings.php is owned by the webserver user. - // This is an inherent security weakness because it allows a malicious - // webserver process to append arbitrary PHP code and then execute it. - // However, it is also a common configuration on shared hosting, and - // there is nothing Drupal can do to prevent it. In this situation, - // having settings.php also owned by the webserver does not introduce - // any additional security risk, so we keep the file in place. - if (fileowner($default_settings_file) === fileowner($settings_file)) { + // If Drupal is not set up already, we need to create a settings file. + foreach ($default_files as $file => $default_file_info) { + if (!$install_state['settings_verified']) { + $readable = FALSE; + $writable = FALSE; + $conf_path = './' . conf_path(FALSE); + $settings_file = $conf_path . "/{$default_file_info['file']}"; + $default_settings_file = "./sites/default/{$default_file_info['file_default']}"; + $file = $conf_path; + $exists = FALSE; + // Verify that the directory exists. + if (drupal_verify_install_file($conf_path, FILE_EXIST, 'dir')) { + // Check if a $file file already exists. + $file = $settings_file; + if (drupal_verify_install_file($settings_file, FILE_EXIST)) { + // If it does, make sure it is writable. $readable = drupal_verify_install_file($settings_file, FILE_READABLE); $writable = drupal_verify_install_file($settings_file, FILE_WRITABLE); $exists = TRUE; } - // If settings.php and default.settings.php have different owners, this - // probably means the server is set up "securely" (with the webserver - // running as its own user, distinct from the user who owns all the - // Drupal PHP files), although with either a group or world writable - // sites directory. Keeping settings.php owned by the webserver would - // therefore introduce a security risk. It would also cause a usability - // problem, since site owners who do not have root access to the file - // system would be unable to edit their settings file later on. We - // therefore must delete the file we just created and force the - // administrator to log on to the server and create it manually. - else { - $deleted = @drupal_unlink($settings_file); - // We expect deleting the file to be successful (since we just - // created it ourselves above), but if it fails somehow, we set a - // variable so we can display a one-time error message to the - // administrator at the bottom of the requirements list. We also try - // to make the file writable, to eliminate any conflicting error - // messages in the requirements list. - $exists = !$deleted; - if ($exists) { - $settings_file_ownership_error = TRUE; + } + + // If the default $file does not exist, or is not readable, throw an + // error. + if (!drupal_verify_install_file($default_settings_file, FILE_EXIST | FILE_READABLE)) { + $requirements["default $file file exists"] = array( + 'title' => $default_file_info['title_default'], + 'value' => $default_file_info['description_default'], + 'severity' => REQUIREMENT_ERROR, + 'description' => t('The @drupal installer requires that the %default-file file not be modified in any way from the original download.', array( + '@drupal' => drupal_install_profile_distribution_name(), + '%default-file' => $default_settings_file + )), + ); + } + // Otherwise, if $file does not exist yet, we can try to copy + // default.$file to create it. + elseif (!$exists) { + $copied = drupal_verify_install_file($conf_path, FILE_EXIST | FILE_WRITABLE, 'dir') && @copy($default_settings_file, $settings_file); + if ($copied) { + // If the new $file file has the same owner as default.$file + // this means default.$file is owned by the webserver user. + // This is an inherent security weakness because it allows a malicious + // webserver process to append arbitrary PHP code and then execute it. + // However, it is also a common configuration on shared hosting, and + // there is nothing Drupal can do to prevent it. In this situation, + // having $file also owned by the webserver does not introduce + // any additional security risk, so we keep the file in place. + if (fileowner($default_settings_file) === fileowner($settings_file)) { $readable = drupal_verify_install_file($settings_file, FILE_READABLE); $writable = drupal_verify_install_file($settings_file, FILE_WRITABLE); + $exists = TRUE; + } + // If $file and default.$file have different owners, this + // probably means the server is set up "securely" (with the webserver + // running as its own user, distinct from the user who owns all the + // Drupal PHP files), although with either a group or world writable + // sites directory. Keeping $file owned by the webserver would + // therefore introduce a security risk. It would also cause a usability + // problem, since site owners who do not have root access to the file + // system would be unable to edit their settings file later on. We + // therefore must delete the file we just created and force the + // administrator to log on to the server and create it manually. + else { + $deleted = @drupal_unlink($settings_file); + // We expect deleting the file to be successful (since we just + // created it ourselves above), but if it fails somehow, we set a + // variable so we can display a one-time error message to the + // administrator at the bottom of the requirements list. We also try + // to make the file writable, to eliminate any conflicting error + // messages in the requirements list. + $exists = !$deleted; + if ($exists) { + $settings_file_ownership_error = TRUE; + $readable = drupal_verify_install_file($settings_file, FILE_READABLE); + $writable = drupal_verify_install_file($settings_file, FILE_WRITABLE); + } } } } - } - // If settings.php does not exist, throw an error. - if (!$exists) { - $requirements['settings file exists'] = array( - 'title' => t('Settings file'), - 'value' => t('The settings file does not exist.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => t('The @drupal installer requires that you create a settings file as part of the installation process. Copy the %default_file file to %file. More details about installing Drupal are available in INSTALL.txt.', array('@drupal' => drupal_install_profile_distribution_name(), '%file' => $file, '%default_file' => $default_settings_file, '@install_txt' => base_path() . 'core/INSTALL.txt')), - ); - } - else { - $requirements['settings file exists'] = array( - 'title' => t('Settings file'), - 'value' => t('The %file file exists.', array('%file' => $file)), - ); - // If settings.php is not readable, throw an error. - if (!$readable) { - $requirements['settings file readable'] = array( - 'title' => t('Settings file'), - 'value' => t('The settings file is not readable.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => t('@drupal requires read permissions to %file at all times. If you are unsure how to grant file permissions, consult the online handbook.', array('@drupal' => drupal_install_profile_distribution_name(), '%file' => $file, '@handbook_url' => 'http://drupal.org/server-permissions')), - ); - } - // If settings.php is not writable, throw an error. - if (!$writable) { - $requirements['settings file writable'] = array( - 'title' => t('Settings file'), - 'value' => t('The settings file is not writable.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => t('The @drupal installer requires write permissions to %file during the installation process. If you are unsure how to grant file permissions, consult the online handbook.', array('@drupal' => drupal_install_profile_distribution_name(), '%file' => $file, '@handbook_url' => 'http://drupal.org/server-permissions')), + // If settings.php does not exist, throw an error. + if (!$exists) { + $requirements["$file file exists"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The %file does not exist.', array('%file' => $default_file_info['title'])), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('The @drupal installer requires that you create a %file as part of the installation process. Copy the %default_file file to %file. More details about installing Drupal are available in INSTALL.txt.', array( + '@drupal' => drupal_install_profile_distribution_name(), + '%file' => $file, + '%default_file' => $default_settings_file, + '@install_txt' => base_path() . 'core/INSTALL.txt' + )), ); } else { - $requirements['settings file'] = array( - 'title' => t('Settings file'), - 'value' => t('The settings file is writable.'), - ); - } - if (!empty($settings_file_ownership_error)) { - $requirements['settings file ownership'] = array( - 'title' => t('Settings file'), - 'value' => t('The settings file is owned by the web server.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => t('The @drupal installer failed to create a settings file with proper file ownership. Log on to your web server, remove the existing %file file, and create a new one by copying the %default_file file to %file. More details about installing Drupal are available in INSTALL.txt. If you have problems with the file permissions on your server, consult the online handbook.', array('@drupal' => drupal_install_profile_distribution_name(), '%file' => $file, '%default_file' => $default_settings_file, '@install_txt' => base_path() . 'core/INSTALL.txt', '@handbook_url' => 'http://drupal.org/server-permissions')), + $requirements["$file file exists"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The %file exists.', array('%file' => $file)), ); + // If settings.php is not readable, throw an error. + if (!$readable) { + $requirements["$file file readable"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The %file is not readable.', array('%file' => $default_file_info['title'])), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('@drupal requires read permissions to %file at all times. If you are unsure how to grant file permissions, consult the online handbook.', array( + '@drupal' => drupal_install_profile_distribution_name(), + '%file' => $file, + '@handbook_url' => 'http://drupal.org/server-permissions' + )), + ); + } + // If settings.php is not writable, throw an error. + if (!$writable) { + $requirements["$file file writeable"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The %file is not writable.', array('%file' => $default_file_info['title'])), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('The @drupal installer requires write permissions to %file during the installation process. If you are unsure how to grant file permissions, consult the online handbook.', array( + '@drupal' => drupal_install_profile_distribution_name(), + '%file' => $file, + '@handbook_url' => 'http://drupal.org/server-permissions' + )), + ); + } + else { + $requirements["$file file"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The @file is writable.', array('@file' => $default_file_info['title'])), + ); + } + if (!empty($settings_file_ownership_error)) { + $requirements["$file file ownership"] = array( + 'title' => $default_file_info['title'], + 'value' => t('The @file is owned by the web server.', array('@file' => $default_file_info['title'])), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('The @drupal installer failed to create a %file file with proper file ownership. Log on to your web server, remove the existing %file file, and create a new one by copying the %default_file file to %file. More details about installing Drupal are available in INSTALL.txt. If you have problems with the file permissions on your server, consult the online handbook.', array( + '@drupal' => drupal_install_profile_distribution_name(), + '%file' => $file, + '%default_file' => $default_settings_file, + '@install_txt' => base_path() . 'core/INSTALL.txt', + '@handbook_url' => 'http://drupal.org/server-permissions' + )), + ); + } } } } diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index 11b9e3e..7912ef3 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -43,7 +43,8 @@ class CoreServiceProvider implements ServiceProviderInterface { * {@inheritdoc} */ public function register(ContainerBuilder $container) { - $this->registerTwig($container); + $container->setParameter('app.root', DRUPAL_ROOT); + $this->registerUuid($container); $this->registerTest($container); @@ -77,44 +78,6 @@ public function register(ContainerBuilder $container) { } /** - * Registers Twig services. - * - * This method is public and static so that it can be reused in the installer. - */ - public static function registerTwig(ContainerBuilder $container) { - $container->register('twig.loader.filesystem', 'Twig_Loader_Filesystem') - ->addArgument(DRUPAL_ROOT); - $container->setAlias('twig.loader', 'twig.loader.filesystem'); - - $twig_extension = new Definition('Drupal\Core\Template\TwigExtension'); - $twig_extension->addMethodCall('setGenerators', array(new Reference('url_generator'))); - - $container->register('twig', 'Drupal\Core\Template\TwigEnvironment') - ->addArgument(new Reference('twig.loader')) - ->addArgument(array( - // This is saved / loaded via drupal_php_storage(). - // All files can be refreshed by clearing caches. - // @todo ensure garbage collection of expired files. - // When in the installer, twig_cache must be FALSE until we know the - // files folder is writable. - 'cache' => drupal_installation_attempted() ? FALSE : Settings::get('twig_cache', TRUE), - 'autoescape' => TRUE, - 'debug' => Settings::get('twig_debug', FALSE), - 'auto_reload' => Settings::get('twig_auto_reload', NULL), - )) - ->addArgument(new Reference('module_handler')) - ->addArgument(new Reference('theme_handler')) - ->addMethodCall('addExtension', array($twig_extension)) - // @todo Figure out what to do about debugging functions. - // @see http://drupal.org/node/1804998 - ->addMethodCall('addExtension', array(new Definition('Twig_Extension_Debug'))) - ->addTag('service_collector', array( - 'tag' => 'twig.extension', - 'call' => 'addExtension', - )); - } - - /** * Determines and registers the UUID service. * * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php index 75282d2..d4ae53e 100644 --- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php @@ -53,6 +53,14 @@ public function __construct(ContainerBuilder $container) } /** + * Resets the internal cache. This method is mostly useful for tests. + */ + public static function reset() + { + static::$yaml = array(); + } + + /** * Loads a Yaml file. * * @param mixed $file The resource diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php index 6c393b1..d64bcbb 100644 --- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php +++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php @@ -60,6 +60,11 @@ public function register(ContainerBuilder $container) { * {@inheritdoc} */ public function alter(ContainerBuilder $container) { + // Disable Twig cache (php storage does not exist yet). + $twig_config = $container->getParameter('twig.config'); + $twig_config['cache'] = FALSE; + $container->setParameter('twig.config', $twig_config); + // Disable configuration overrides. // ConfigFactory would to try to load language overrides and InstallStorage // throws an exception upon trying to load a non-existing file. diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php index 717ee04..5ed35cd 100644 --- a/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php @@ -29,7 +29,7 @@ class KeyValueFactory implements KeyValueFactoryInterface { * This is a setting name that will be used if the specific setting does not * exist. The setting value will be the id of a service. */ - const DEFAULT_SETTING = 'keyvalue_default'; + const DEFAULT_SETTING = 'default'; /** * The default service id. @@ -51,21 +51,23 @@ class KeyValueFactory implements KeyValueFactoryInterface { protected $container; /** - * The read-only settings container. + * Collection-specific storage override options. * - * @var \Drupal\Core\Site\Settings + * Keys are collection names, values are service IDs. + * + * @var array */ protected $settings; /** * @param \Symfony\Component\DependencyInjection\ContainerInterface $container * The service container. - * @param \Drupal\Core\Site\Settings $settings - * The read-only settings container. + * @param array $options + * (optional) Collection-specific storage override options. */ - function __construct(ContainerInterface $container, Settings $settings) { + function __construct(ContainerInterface $container, array $options = array()) { $this->container = $container; - $this->settings = $settings; + $this->options = $options; } /** @@ -73,14 +75,16 @@ function __construct(ContainerInterface $container, Settings $settings) { */ public function get($collection) { if (!isset($this->stores[$collection])) { - if ($service_name = $this->settings->get(static::SPECIFIC_PREFIX . $collection)) { + if (isset($this->options[$collection])) { + $service_id = $this->options[$collection]; } - elseif ($service_name = $this->settings->get(static::DEFAULT_SETTING)) { + elseif (isset($this->options[static::DEFAULT_SETTING])) { + $service_id = $this->options[static::DEFAULT_SETTING]; } else { - $service_name = static::DEFAULT_SERVICE; + $service_id = static::DEFAULT_SERVICE; } - $this->stores[$collection] = $this->container->get($service_name)->get($collection); + $this->stores[$collection] = $this->container->get($service_id)->get($collection); } return $this->stores[$collection]; } diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index d8da1ca..fba0173 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -41,7 +41,7 @@ class TwigEnvironment extends \Twig_Environment { * Constructs a TwigEnvironment object and stores cache and storage * internally. */ - public function __construct(\Twig_LoaderInterface $loader = NULL, $options = array(), ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) { + public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, $options = array()) { // @todo Pass as arguments from the DIC. $this->cache_object = \Drupal::cache(); @@ -68,6 +68,16 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, $options = arr $this->templateClasses = array(); $this->stringLoader = new \Twig_Loader_String(); + $options += array( + // @todo Ensure garbage collection of expired files. + 'cache' => TRUE, + // @todo Remove this. + // @see http://drupal.org/node/1712444 + 'autoescape' => FALSE, + 'debug' => FALSE, + 'auto_reload' => NULL, + ); + parent::__construct($loader, $options); } diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 616d064..154f7cf 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -260,7 +260,9 @@ public function containerBuild(ContainerBuilder $container) { ->addArgument(Database::getConnection()) ->addArgument('config'); - $this->settingsSet('keyvalue_default', 'keyvalue.memory'); + $keyvalue_config = $container->getParameter('factory.keyvalue') ?: array(); + $keyvalue_config['default'] = 'keyvalue.memory'; + $container->setParameter('factory.keyvalue', $keyvalue_config); $container->set('keyvalue.memory', $this->keyValueFactory); if (!$container->has('keyvalue')) { // TestBase::setUp puts a completely empty container in @@ -280,7 +282,7 @@ public function containerBuild(ContainerBuilder $container) { $container ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory') ->addArgument(new Reference('service_container')) - ->addArgument(new Reference('settings')); + ->addArgument(new Parameter('factory.keyvalue')); $container->register('state', 'Drupal\Core\State\State') ->addArgument(new Reference('keyvalue')); diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index e0b6858..0b41508 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -8,9 +8,11 @@ namespace Drupal\simpletest; use Drupal\Component\Serialization\Json; +use Drupal\Component\Serialization\Yaml; use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; +use Drupal\Core\DependencyInjection\YamlFileLoader; use Drupal\Core\DrupalKernel; use Drupal\Core\Database\Database; use Drupal\Core\Database\ConnectionNotDefinedException; @@ -815,6 +817,7 @@ protected function setUp() { // 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'); // All file system paths are created by System module during installation. // @see system_requirements() @@ -1022,6 +1025,26 @@ protected function writeSettings(array $settings) { } /** + * Changes parameters in the services.yml file. + * + * @param $name + * The name of the parameter. + * @param $value + * The value of the parameter. + */ + protected function containerParameterSet($name, $value) { + $filename = $this->siteDirectory . '/services.yml'; + chmod($filename, 0666); + + $services = Yaml::decode(file_get_contents($filename)); + $services['parameters'][$name] = $value; + file_put_contents($filename, Yaml::encode($services)); + + // Clear the YML file cache. + YamlFileLoader::reset(); + } + + /** * Queues custom translations to be written to settings.php. * * Use WebTestBase::writeCustomTranslations() to apply and write the queued diff --git a/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageExpirableTest.php b/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageExpirableTest.php index b18befa..86a2bfb 100644 --- a/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageExpirableTest.php +++ b/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageExpirableTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\KeyValueStore; +use Drupal\Core\KeyValueStore\KeyValueFactory; use Symfony\Component\DependencyInjection\Reference; /** @@ -18,8 +19,9 @@ class DatabaseStorageExpirableTest extends StorageTestBase { protected function setUp() { parent::setUp(); + $this->factory = 'keyvalue.expirable'; - module_load_install('system'); + include_once DRUPAL_ROOT . '/core/modules/system/system.install'; $schema = system_schema(); db_create_table('key_value_expire', $schema['key_value_expire']); $this->container @@ -33,7 +35,9 @@ protected function setUp() { ->addArgument(new Reference('database')); $this->container ->register('serialization.phpserialize', 'Drupal\Component\Serialization\PhpSerialize'); - $this->settingsSet('keyvalue_expirable_default', 'keyvalue.expirable.database'); + $parameter = array(); + $parameter[KeyValueFactory::DEFAULT_SETTING] = 'keyvalue.expirable.database'; + $this->container->setParameter('factory.keyvalue.expirable', $parameter); } protected function tearDown() { diff --git a/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageTest.php b/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageTest.php index f3f61be..3bdab70 100644 --- a/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageTest.php +++ b/core/modules/system/src/Tests/KeyValueStore/DatabaseStorageTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\KeyValueStore; +use Drupal\Core\KeyValueStore\KeyValueFactory; use Symfony\Component\DependencyInjection\Reference; /** @@ -18,7 +19,7 @@ class DatabaseStorageTest extends StorageTestBase { protected function setUp() { parent::setUp(); - module_load_install('system'); + include_once DRUPAL_ROOT . '/core/modules/system/system.install'; $schema = system_schema(); db_create_table('key_value', $schema['key_value']); $this->container @@ -32,7 +33,9 @@ protected function setUp() { ->addArgument(new Reference('database')); $this->container ->register('serialization.phpserialize', 'Drupal\Component\Serialization\PhpSerialize'); - $this->settingsSet('keyvalue_default', 'keyvalue.database'); + $parameter = array(); + $parameter[KeyValueFactory::DEFAULT_SETTING] = 'keyvalue.database'; + $this->container->setParameter('factory.keyvalue', $parameter); } protected function tearDown() { diff --git a/core/modules/system/src/Tests/KeyValueStore/MemoryStorageTest.php b/core/modules/system/src/Tests/KeyValueStore/MemoryStorageTest.php index 10b2a15..770d758 100644 --- a/core/modules/system/src/Tests/KeyValueStore/MemoryStorageTest.php +++ b/core/modules/system/src/Tests/KeyValueStore/MemoryStorageTest.php @@ -6,6 +6,7 @@ */ namespace Drupal\system\Tests\KeyValueStore; +use Drupal\Core\KeyValueStore\KeyValueFactory; /** * Tests the key-value memory storage. @@ -25,7 +26,9 @@ protected function setUp() { parent::setUp(); $this->container ->register('keyvalue.memory', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory'); - $this->settingsSet('keyvalue_default', 'keyvalue.memory'); + $parameter = array(); + $parameter[KeyValueFactory::DEFAULT_SETTING] = 'keyvalue.memory'; + $this->container->setParameter('factory.keyvalue', $parameter); } } diff --git a/core/modules/system/src/Tests/KeyValueStore/StorageTestBase.php b/core/modules/system/src/Tests/KeyValueStore/StorageTestBase.php index 0190e6b..0d3bcd0 100644 --- a/core/modules/system/src/Tests/KeyValueStore/StorageTestBase.php +++ b/core/modules/system/src/Tests/KeyValueStore/StorageTestBase.php @@ -9,6 +9,7 @@ use Drupal\simpletest\UnitTestBase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; /** @@ -58,11 +59,11 @@ protected function setUp() { $this->container ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory') ->addArgument(new Reference('service_container')) - ->addArgument(new Reference('settings')); + ->addArgument('%factory.keyvalue%'); $this->container ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueExpirableFactory') ->addArgument(new Reference('service_container')) - ->addArgument(new Reference('settings')); + ->addArgument('%factory.keyvalue.expirable%'); // Define two data collections, $this->collections = array(0 => 'zero', 1 => 'one'); diff --git a/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php b/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php index 2836c2c..653e802 100644 --- a/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php +++ b/core/modules/system/src/Tests/Theme/TwigDebugMarkupTest.php @@ -31,7 +31,9 @@ function testTwigDebugMarkup() { theme_enable(array('test_theme')); \Drupal::config('system.theme')->set('default', 'test_theme')->save(); // Enable debug, rebuild the service container, and clear all caches. - $this->settingsSet('twig_debug', TRUE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['debug'] = TRUE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); $this->resetAll(); @@ -67,7 +69,9 @@ function testTwigDebugMarkup() { $this->assertTrue(strpos($output, '* node--foo--bar' . $extension . PHP_EOL . ' * node--foo' . $extension . PHP_EOL . ' * node--3--full' . $extension . PHP_EOL . ' * node--3' . $extension . PHP_EOL . ' * node--page--full' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' * node--full' . $extension . PHP_EOL . ' x node' . $extension) !== FALSE, 'Suggested template files found in order and base template shown as current template.'); // Disable debug, rebuild the service container, and clear all caches. - $this->settingsSet('twig_debug', FALSE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['debug'] = FALSE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); $this->resetAll(); diff --git a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php index 630fc14..597ba5b 100644 --- a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php +++ b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php @@ -29,14 +29,18 @@ class TwigSettingsTest extends WebTestBase { */ function testTwigAutoReloadOverride() { // Enable auto reload and rebuild the service container. - $this->settingsSet('twig_auto_reload', TRUE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['auto_reload'] = TRUE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); // Check isAutoReload() via the Twig service container. $this->assertTrue($this->container->get('twig')->isAutoReload(), 'Automatic reloading of Twig templates enabled.'); // Disable auto reload and check the service container again. - $this->settingsSet('twig_auto_reload', FALSE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['auto_reload'] = FALSE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); $this->assertFalse($this->container->get('twig')->isAutoReload(), 'Automatic reloading of Twig templates disabled.'); @@ -47,7 +51,9 @@ function testTwigAutoReloadOverride() { */ function testTwigDebugOverride() { // Enable debug and rebuild the service container. - $this->settingsSet('twig_debug', TRUE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['debug'] = TRUE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); // Check isDebug() via the Twig service container. @@ -55,12 +61,16 @@ function testTwigDebugOverride() { $this->assertTrue($this->container->get('twig')->isAutoReload(), 'Twig automatic reloading is enabled when debug is enabled.'); // Override auto reload when debug is enabled. - $this->settingsSet('twig_auto_reload', FALSE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['auto_reload'] = FALSE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); $this->assertFalse($this->container->get('twig')->isAutoReload(), 'Twig automatic reloading can be disabled when debug is enabled.'); // Disable debug and check the service container again. - $this->settingsSet('twig_debug', FALSE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['debug'] = FALSE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); $this->assertFalse($this->container->get('twig')->isDebug(), 'Twig debug disabled.'); @@ -99,7 +109,9 @@ function testTwigCacheOverride() { $this->assertTrue(PhpStorageFactory::get('twig')->exists($cache_filename), 'Cached Twig template found.'); // Disable the Twig cache and rebuild the service container. - $this->settingsSet('twig_cache', FALSE); + $parameters = $this->container->getParameter('twig.config'); + $parameters['cache'] = FALSE; + $this->containerParameterSet('twig.config', $parameters); $this->rebuildContainer(); // This should return false after rebuilding the service container. diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml new file mode 100644 index 0000000..1087bc5 --- /dev/null +++ b/sites/default/default.services.yml @@ -0,0 +1,62 @@ +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). + # + # Note: changes to this setting will only take effect once the cache is + # cleared. + # + # 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. + # + # Note: changes to this setting will only take effect once the cache is + # cleared. + # + # 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. + # + # Note: changes to this setting will only take effect once the cache is + # cleared. + # + # 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/example.settings.local.php b/sites/example.settings.local.php index 19f398c..b602a97 100644 --- a/sites/example.settings.local.php +++ b/sites/example.settings.local.php @@ -33,56 +33,3 @@ * using these parameters in a request to rebuild.php. */ $settings['rebuild_access'] = TRUE; - -/** - * 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). - * - * Note: changes to this setting will only take effect once the cache is - * cleared. - * - * For more information about debugging Twig templates, see - * http://drupal.org/node/1906392. - * - * Not recommended in production environments (Default: FALSE). - */ -# $settings['twig_debug'] = TRUE; - -/** - * 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. - * - * Note: changes to this setting will only take effect once the cache is - * cleared. - * - * Not recommended in production environments (Default: NULL). - */ -# $settings['twig_auto_reload'] = TRUE; - -/** - * 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. - * - * Note: changes to this setting will only take effect once the cache is - * cleared. - * - * Not recommended in production environments (Default: TRUE). - */ -# $settings['twig_cache'] = FALSE;