diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 3453b2a..09bfa00 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -1,7 +1,6 @@ setParameter('database.info', $databases); + } } $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; @@ -2241,15 +2243,14 @@ function _drupal_bootstrap_configuration() { drupal_environment_initialize(); // Start a page timer: timer_start('page'); + // Activate the class loader. + drupal_classloader(); // Initialize the configuration, including variables from settings.php. drupal_settings_initialize(); // Make sure we are using the test database prefix in child Drupal sites. _drupal_initialize_db_test_prefix(); - // Activate the class loader. - drupal_classloader(); - // Load the procedural configuration system helper functions. require_once DRUPAL_ROOT . '/core/includes/config.inc'; } @@ -2323,7 +2324,8 @@ function _drupal_initialize_db_test_prefix() { $test_info['test_run_id'] = $test_prefix; $test_info['in_child_site'] = TRUE; - foreach ($GLOBALS['databases']['default'] as &$value) { + $databases = drupal_container()->getParameter('database.info'); + foreach ($databases['default'] as &$value) { // Extract the current default database prefix. if (!isset($value['prefix'])) { $current_prefix = ''; @@ -2340,6 +2342,7 @@ function _drupal_initialize_db_test_prefix() { 'default' => $current_prefix . $test_prefix, ); } + drupal_container()->setParameter('database.info', $databases); } } @@ -2350,12 +2353,11 @@ function _drupal_bootstrap_database() { // Redirect the user to the installation script if Drupal has not been // installed yet (i.e., if no $databases array has been defined in the // settings.php file) and we are not already installing. - if (empty($GLOBALS['databases']) && !drupal_installation_attempted()) { + if (!drupal_container()->hasParameter('database.info') && !drupal_installation_attempted()) { include_once DRUPAL_ROOT . '/core/includes/install.inc'; install_goto('core/install.php'); } - // Initialize the database system. Note that the connection // won't be initialized until it is actually requested. require_once DRUPAL_ROOT . '/core/includes/database.inc'; @@ -2440,12 +2442,38 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) { $container ->register('config.cachedstorage.storage', 'Drupal\Core\Config\FileStorage') ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY)); - // @todo Replace this with a cache.factory service plus 'config' argument. - $container - ->register('cache.config') - ->setFactoryClass('Drupal\Core\Cache\CacheFactory') - ->setFactoryMethod('get') - ->addArgument('config'); + + // This will be overridden by settings.php in drupal_settings_initialize(). + $container->setParameter('database.info', array()); + $container->register('database', 'Drupal\Core\Database\Connection') + ->setFactoryClass('Drupal\Core\Database\Database') + ->setFactoryMethod('getConnection') + ->addArgument('default') + ->addArgument(NULL) + ->addArgument('%database.info%'); + $container->register('database.slave', 'Drupal\Core\Database\Connection') + ->setFactoryClass('Drupal\Core\Database\Database') + ->setFactoryMethod('getConnection') + ->addArgument('slave') + ->addArgument(NULL) + ->addArgument('%database.info%'); + // settings.php might have registered an alternative cache implementation + // already. + if (!$container->has('cache')) { + $container->register('cache', 'Drupal\Core\Cache\DatabaseBackend') + ->addArgument('cache') + ->addArgument(new Reference('database')) + ->addTag('cache'); + } + foreach (array('bootstrap', 'config', 'page') as $bin) { + $id = 'cache.' . $bin; + if (!$container->has($id)) { + // A clone is necessary otherwise the replaceArgument call would change + // every definition. + $definition = clone $container->getDefinition('cache'); + $container->setDefinition($id, $definition->replaceArgument(0, $bin)); + } + } $container ->register('config.storage', 'Drupal\Core\Config\CachedStorage') diff --git a/core/includes/cache.inc b/core/includes/cache.inc index 341d77f..6af6fe1 100644 --- a/core/includes/cache.inc +++ b/core/includes/cache.inc @@ -5,16 +5,8 @@ * Functions and interfaces for cache handling. */ -use Drupal\Core\Cache\CacheFactory; - /** - * Instantiates and statically caches the correct class for a cache bin. - * - * By default, this returns an instance of the Drupal\Core\Cache\DatabaseBackend - * class. - * - * Classes implementing Drupal\Core\Cache\CacheBackendInterface can register - * themselves both as a default implementation and for specific bins. + * Returns a cache service. * * @param $bin * The cache bin for which the cache object should be returned, defaults to @@ -26,21 +18,8 @@ * @see Drupal\Core\Cache\CacheBackendInterface */ function cache($bin = 'cache') { - // Use the advanced drupal_static() pattern, since this is called very often. - static $drupal_static_fast; - if (!isset($drupal_static_fast)) { - $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__, array()); - } - $cache_objects = &$drupal_static_fast['cache']; - - // Temporary backwards compatibiltiy layer, allow old style prefixed cache - // bin names to be passed as arguments. - $bin = str_replace('cache_', '', $bin); - - if (!isset($cache_objects[$bin])) { - $cache_objects[$bin] = CacheFactory::get($bin); - } - return $cache_objects[$bin]; + $service = $bin == 'cache' ? 'cache' : 'cache.' . $bin; + return drupal_container()->get($service); } /** @@ -57,7 +36,10 @@ function cache($bin = 'cache') { * The list of tags to invalidate cache items for. */ function cache_invalidate(array $tags) { - foreach (CacheFactory::getBackends() as $bin => $class) { - cache($bin)->invalidateTags($tags); + $container = drupal_container(); + // @todo: This is method is only available on the ContainerBuilder and needs + // to be moved to a compiler pass once the container is compiled to disk. + foreach (array_keys($container->findTaggedServiceIds('cache')) as $name) { + $container->get($name)->invalidateTags($tags); } } diff --git a/core/includes/common.inc b/core/includes/common.inc index b3dc9cb..e87798f 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -4809,10 +4809,10 @@ function drupal_json_decode($var) { * A salt based on information in settings.php, not in the database. */ function drupal_get_hash_salt() { - global $drupal_hash_salt, $databases; + global $drupal_hash_salt; // If the $drupal_hash_salt variable is empty, a hash of the serialized // database credentials is used as a fallback salt. - return empty($drupal_hash_salt) ? hash('sha256', serialize($databases)) : $drupal_hash_salt; + return empty($drupal_hash_salt) ? hash('sha256', serialize(drupal_container()->getParameter('database.info'))) : $drupal_hash_salt; } /** diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index b1d3b50..d447bc3 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -346,7 +346,22 @@ function install_begin_request(&$install_state) { // because any data put in the cache during the installer is inherently // suspect, due to the fact that Drupal is not fully set up yet. require_once DRUPAL_ROOT . '/core/includes/cache.inc'; - $conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\InstallBackend'); + $database = NULL; + if (drupal_container()->hasParameter('database.info')) { + // Pass the database to the cacke backend if the connection information + // is available. + $database = new Reference('database'); + } + $container = drupal_container(); + $container->register('cache', 'Drupal\Core\Cache\InstallBackend') + ->addArgument('cache') + ->addArgument($database); + $container->register('cache.bootstrap', 'Drupal\Core\Cache\InstallBackend') + ->addArgument('bootstrap') + ->addArgument($database); + $container->register('cache.form', 'Drupal\Core\Cache\InstallBackend') + ->addArgument('form') + ->addArgument($database); // The install process cannot use the database lock backend since the database // is not fully up, so we use a null backend implementation during the @@ -372,6 +387,15 @@ function install_begin_request(&$install_state) { // Initialize the database system. Note that the connection // won't be initialized until it is actually requested. require_once DRUPAL_ROOT . '/core/includes/database.inc'; + $container->register('cache', 'Drupal\Core\Cache\DatabaseBackend') + ->addArgument('cache') + ->addArgument(new Reference('database')); + $container->register('cache.bootstrap', 'Drupal\Core\Cache\DatabaseBackend') + ->addArgument('bootstrap') + ->addArgument(new Reference('database')); + $container->register('cache.form', 'Drupal\Core\Cache\DatabaseBackend') + ->addArgument('form') + ->addArgument(new Reference('database')); // Verify the last completed task in the database, if there is one. $task = install_verify_completed_task(); @@ -496,7 +520,14 @@ function install_run_task($task, &$install_state) { // We need to pass $install_state by reference in order for forms to // modify it, since the form API will use it in call_user_func_array(), // which requires that referenced variables be passed explicitly. - 'build_info' => array('args' => array(&$install_state)), + 'build_info' => array( + 'args' => array(&$install_state), + // drupal_retrieve_form() tries to load the current menu item + // if this is not set. + 'files' => array( + 'menu' => FALSE, + ) + ), ); drupal_form_submit($function, $form_state); $errors = form_get_errors(); @@ -939,8 +970,9 @@ function install_verify_completed_task() { * Verifies that settings.php specifies a valid database connection. */ function install_verify_database_settings() { - global $databases; - if (!empty($databases)) { + $container = drupal_container(); + if ($container->hasParameter('database.info')) { + $databases = $container->getParameter('database.info'); $database = $databases['default']['default']; drupal_static_reset('conf_path'); $settings_file = './' . conf_path(FALSE) . '/settings.php'; @@ -963,13 +995,16 @@ function install_verify_database_settings() { * @ingroup forms */ function install_settings_form($form, &$form_state, &$install_state) { - global $databases; $profile = $install_state['parameters']['profile']; drupal_static_reset('conf_path'); $conf_path = './' . conf_path(FALSE); $settings_file = $conf_path . '/settings.php'; - $database = isset($databases['default']['default']) ? $databases['default']['default'] : array(); + $database = array(); + if (drupal_container()->hasParameter('database.info')) { + $databases = drupal_container()->getParameter('database.info'); + $database = isset($databases['default']['default']) ? $databases['default']['default'] : array(); + } drupal_set_title(st('Database configuration')); @@ -1037,6 +1072,7 @@ function install_settings_form_validate($form, &$form_state) { unset($database['db_prefix']); $form_state['storage']['database'] = $database; + drupal_container()->setParameter('database.info', array('default' => $database)); $errors = install_database_errors($database, $form_state['values']['settings_file']); foreach ($errors as $name => $message) { form_set_error($name, $message); @@ -1047,7 +1083,6 @@ function install_settings_form_validate($form, &$form_state) { * Checks a database connection and returns any errors. */ function install_database_errors($database, $settings_file) { - global $databases; $errors = array(); // Check database type. @@ -1062,17 +1097,15 @@ function install_database_errors($database, $settings_file) { // Run tasks associated with the database type. Any errors are caught in the // calling function. - $databases['default']['default'] = $database; // Just changing the global doesn't get the new information processed. // We need to close any active connections and tell the Database class to // re-parse $databases. if (Database::isActiveConnection()) { Database::closeConnection(); } - Database::parseConnectionInfo(); try { - db_run_tasks($driver); + db_run_tasks($driver, $database); } catch (TaskException $e) { // These are generic errors, so we do not have any specific key of the diff --git a/core/includes/install.inc b/core/includes/install.inc index db92987..9b4441a 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -933,8 +933,8 @@ function install_profile_info($profile, $langcode = 'en') { * TABLE to database specific functions like stored procedures and client * encoding. */ -function db_run_tasks($driver) { - db_installer_object($driver)->runTasks(); +function db_run_tasks($driver, $database) { + db_installer_object($driver, $database)->runTasks(); return TRUE; } @@ -944,9 +944,9 @@ function db_run_tasks($driver) { * @param $driver * The name of the driver. */ -function db_installer_object($driver) { +function db_installer_object($driver, $database = NULL) { // We cannot use Database::getConnection->getDriverClass() here, because // the connection object is not yet functional. $task_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Install\\Tasks"; - return new $task_class(); + return new $task_class($database); } diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 9c4f8fc..de61459 100644 --- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -12,34 +12,44 @@ * * All cache implementations have to implement this interface. * Drupal\Core\Cache\DatabaseBackend provides the default implementation, which - * can be consulted as an example. + * can be consulted as an example. Additionally, a backend needs to accept the + * cache bin as the first constructor argument, additional arguments can be used + * as necessary. * * To make Drupal use your implementation for a certain cache bin, you have to - * set a variable with the name of the cache bin as its key and the name of - * your class as its value. For example, if your implementation of - * Drupal\Core\Cache\CacheBackendInterface was called MyCustomCache, the - * following line would make Drupal use it for the 'cache_page' bin: + * register it accordingly in the dependency injection container. For example, + * if your implementation of Drupal\Core\Cache\CacheBackendInterface was called + * Drupal\mymodule\MyCustomCache, the following line would make Drupal use it + * for the 'page' bin: * @code - * $conf['cache_classes']['cache_page'] = 'MyCustomCache'; + * drupal_classloader_register('mymodule', 'modules/mymodule'); + * drupal_container()->register('cache.page', 'Drupal\mymodule\MyCustomCache') + * ->addArgument('page') + * ->addTag('cache'); * @endcode * * Additionally, you can register your cache implementation to be used by - * default for all cache bins by setting the $conf['cache_classes'] variable and - * changing the value of the 'cache' key to the name of your implementation of - * the Drupal\Core\Cache\CacheBackendInterface, e.g. + * default for all cache bins. The bins bootstrap, config and page are + * registered too early to use the default definition and need to be overwritten + * explicitly. * @code - * $conf['cache_classes']['cache'] = 'MyCustomCache'; + * $container = drupal_container(); + * $container->register('cache', 'Drupal\mymodule\MyCustomCache') + * ->addArgument('cache') + * ->addTag('cache'); + * foreach (array('bootstrap', 'config', 'page') as $bin) { + * $definition = clone $container->getDefinition('cache'); + * $container->setDefinition($id, $definition->replaceArgument(0, $bin)); + * } * @endcode * - * To implement a completely custom cache bin, use the same variable format: - * @code - * $conf['cache_classes']['custom_bin'] = 'MyCustomCache'; - * @endcode - * To access your custom cache bin, specify the name of the bin when storing - * or retrieving cached data: + * Modules that define their own cache bin need to register it in their module + * bundle using the following code. They also need to define the cache_$bin + * table required by the default cache implementation. + * * @code - * cache('custom_bin')->set($cid, $data, $expire); - * cache('custom_bin')->get($cid); + * $definition = clone $container->getDefinition('cache'); + * $container->setDefinition('cache.custom', $definition->replaceArgument(0, 'custom')); * @endcode * * @see cache() @@ -55,14 +65,6 @@ const CACHE_PERMANENT = 0; /** - * Constructs a new cache backend. - * - * @param $bin - * The cache bin for which the object is created. - */ - public function __construct($bin); - - /** * Returns data from the persistent cache. * * Data may be stored as either plain text or as serialized data. cache_get() diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php deleted file mode 100644 index da42a26..0000000 --- a/core/lib/Drupal/Core/Cache/CacheFactory.php +++ /dev/null @@ -1,56 +0,0 @@ - 'Drupal\Core\Cache\DatabaseBackend'); - return $cache_backends; - } - -} diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index 9ab6b11..d98199e 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Cache; -use Drupal\Core\Database\Database; +use Drupal\Core\Database\Connection; use Exception; /** @@ -24,14 +24,27 @@ class DatabaseBackend implements CacheBackendInterface { protected $bin; /** + * A database connection object. + * + * @var Drupal\Core\Database\Connection + */ + protected $connection; + + /** * A static cache of all tags checked during the request. */ protected static $tagCache = array(); /** - * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). + * Constructs a new cache database backend. + * + * @param string $bin + * (optional) The cache bin that should be used. + * @param Drupal\Core\Database\Connection $connection + * The database connection that should be used. */ - public function __construct($bin) { + function __construct($bin, Connection $connection) { + $this->connection = $connection; // All cache tables should be prefixed with 'cache_', except for the // default 'cache' bin. if ($bin != 'cache') { @@ -61,7 +74,7 @@ public function getMultiple(&$cids) { // is used here only due to the performance overhead we would incur // otherwise. When serving an uncached page, the overhead of using // ::select() is a much smaller proportion of the request. - $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); + $result = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); $cache = array(); foreach ($result as $item) { $item = $this->prepareItem($item); @@ -72,7 +85,7 @@ public function getMultiple(&$cids) { $cids = array_diff($cids, array_keys($cache)); return $cache; } - catch (Exception $e) { + catch (\Exception $e) { // If the database is never going to be available, cache requests should // return FALSE in order to allow exception handling to occur. return array(); @@ -134,7 +147,7 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN } try { - Database::getConnection()->merge($this->bin) + $this->connection->merge($this->bin) ->key(array('cid' => $cid)) ->fields($fields) ->execute(); @@ -148,7 +161,7 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ public function delete($cid) { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('cid', $cid) ->execute(); } @@ -159,7 +172,7 @@ public function delete($cid) { public function deleteMultiple(array $cids) { // Delete in chunks when a large array is passed. do { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('cid', array_splice($cids, 0, 1000), 'IN') ->execute(); } @@ -170,14 +183,14 @@ public function deleteMultiple(array $cids) { * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ public function flush() { - Database::getConnection()->truncate($this->bin)->execute(); + $this->connection->truncate($this->bin)->execute(); } /** * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ public function expire() { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>') ->condition('expire', REQUEST_TIME, '<') ->execute(); @@ -240,7 +253,7 @@ protected function flattenTags(array $tags) { public function invalidateTags(array $tags) { foreach ($this->flattenTags($tags) as $tag) { unset(self::$tagCache[$tag]); - Database::getConnection()->merge('cache_tags') + $this->connection->merge('cache_tags') ->key(array('tag' => $tag)) ->fields(array('invalidations' => 1)) ->expression('invalidations', 'invalidations + 1') @@ -271,7 +284,7 @@ protected function checksumTags($tags) { } if ($query_tags) { try { - if ($db_tags = Database::getConnection()->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) { + if ($db_tags = $this->connection->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) { self::$tagCache = array_merge(self::$tagCache, $db_tags); $checksum += array_sum($db_tags); } @@ -288,7 +301,7 @@ protected function checksumTags($tags) { */ public function isEmpty() { $this->garbageCollection(); - $query = Database::getConnection()->select($this->bin); + $query = $this->connection->select($this->bin); $query->addExpression('1'); $result = $query->range(0, 1) ->execute() diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php index e23294a..d66452c 100644 --- a/core/lib/Drupal/Core/Cache/InstallBackend.php +++ b/core/lib/Drupal/Core/Cache/InstallBackend.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Cache; +use Drupal\Core\Database\Connection; use Exception; /** @@ -34,6 +35,19 @@ class InstallBackend extends DatabaseBackend { /** + * Overrides Drupal\Core\Cache\DatabaseBackend::__construct(). + */ + function __construct($bin, Connection $connection = NULL) { + $this->connection = $connection; + // All cache tables should be prefixed with 'cache_', except for the + // default 'cache' bin. + if ($bin != 'cache') { + $bin = 'cache_' . $bin; + } + $this->bin = $bin; + } + + /** * Overrides Drupal\Core\Cache\DatabaseBackend::get(). */ public function get($cid) { @@ -57,7 +71,7 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN */ public function delete($cid) { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::delete($cid); } } @@ -69,7 +83,7 @@ public function delete($cid) { */ public function deleteMultiple(array $cids) { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::deleteMultiple($cids); } } @@ -81,7 +95,7 @@ public function deleteMultiple(array $cids) { */ public function invalidateTags(array $tags) { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::invalidateTags($tags); } } @@ -93,7 +107,7 @@ public function invalidateTags(array $tags) { */ public function flush() { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::flush(); } } @@ -105,7 +119,7 @@ public function flush() { */ public function expire() { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::expire(); } } @@ -117,7 +131,7 @@ public function expire() { */ public function garbageCollection() { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { parent::garbageCollection(); } } @@ -129,7 +143,7 @@ public function garbageCollection() { */ public function isEmpty() { try { - if (class_exists('Drupal\Core\Database\Database')) { + if ($this->connection) { return parent::isEmpty(); } } diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php index b17e06b..2b4aec7 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackend.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php @@ -29,12 +29,6 @@ class MemoryBackend implements CacheBackendInterface { protected $invalidatedTags = array(); /** - * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). - */ - public function __construct($bin) { - } - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ public function get($cid) { diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php index ee8b1d3..9b587c2 100644 --- a/core/lib/Drupal/Core/Cache/NullBackend.php +++ b/core/lib/Drupal/Core/Cache/NullBackend.php @@ -21,11 +21,6 @@ class NullBackend implements CacheBackendInterface { /** - * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). - */ - public function __construct($bin) {} - - /** * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ public function get($cid) { diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index f1e43d6..4ca478c 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -46,14 +46,17 @@ public function build(ContainerBuilder $container) { $container->register('language_manager', 'Drupal\Core\Language\LanguageManager') ->addArgument(new Reference('request')) ->setScope('request'); - $container->register('database', 'Drupal\Core\Database\Connection') - ->setFactoryClass('Drupal\Core\Database\Database') - ->setFactoryMethod('getConnection') - ->addArgument('default'); - $container->register('database.slave', 'Drupal\Core\Database\Connection') - ->setFactoryClass('Drupal\Core\Database\Database') - ->setFactoryMethod('getConnection') - ->addArgument('slave'); + + foreach (array('block', 'field', 'filter', 'path', 'form', 'menu') as $bin) { + $id = 'cache.' . $bin; + // Only define the bin if it has not yet been defined. + if (!$container->has($id)) { + $definition = clone $container->getDefinition('cache'); + // Each backend must define the bin as it's first constructor argument. + $container->setDefinition($id, $definition->replaceArgument(0, $bin)); + } + } + $container->register('typed_data', 'Drupal\Core\TypedData\TypedDataManager'); // Add the user's storage for temporary, non-cache data. $container->register('lock', 'Drupal\Core\Lock\DatabaseLockBackend'); diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php index 6a425de..70eda58 100644 --- a/core/lib/Drupal/Core/Database/Database.php +++ b/core/lib/Drupal/Core/Database/Database.php @@ -144,15 +144,21 @@ /** * Gets the connection object for the specified database key and target. * - * @param $target + * @param string $target * The database target name. * @param $key * The database connection key. Defaults to NULL which means the active key. + * @param array $database_info + * Database connection information as defined in settings.php. * * @return Drupal\Core\Database\Connection * The corresponding connection object. */ - final public static function getConnection($target = 'default', $key = NULL) { + final public static function getConnection($target = 'default', $key = NULL, $database_info = array()) { + if (empty(self::$databaseInfo)) { + self::parseConnectionInfo($database_info); + } + if (!isset($key)) { // By default, we want the active connection, set in setActiveConnection. $key = self::$activeKey; @@ -195,7 +201,7 @@ */ final public static function setActiveConnection($key = 'default') { if (empty(self::$databaseInfo)) { - self::parseConnectionInfo(); + throw new \LogicException('Database::setActiveConnection is called without specifying the database information first.'); } if (!empty(self::$databaseInfo[$key])) { @@ -208,10 +214,7 @@ /** * Process the configuration file for database information. */ - final public static function parseConnectionInfo() { - global $databases; - - $database_info = is_array($databases) ? $databases : array(); + final public static function parseConnectionInfo($database_info) { foreach ($database_info as $index => $info) { foreach ($database_info[$index] as $target => $value) { // If there is no "driver" property, then we assume it's an array of @@ -287,7 +290,7 @@ public static function addConnectionInfo($key, $target, $info) { */ final public static function getConnectionInfo($key = 'default') { if (empty(self::$databaseInfo)) { - self::parseConnectionInfo(); + throw new \LogicException('Database::getConnectionInfo called without specifying the database information first.'); } if (!empty(self::$databaseInfo[$key])) { @@ -307,7 +310,7 @@ public static function addConnectionInfo($key, $target, $info) { */ final public static function renameConnection($old_key, $new_key) { if (empty(self::$databaseInfo)) { - self::parseConnectionInfo(); + throw new \LogicException('Database::renameConnection called without specifying the database information first.'); } if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) { @@ -359,9 +362,9 @@ public static function addConnectionInfo($key, $target, $info) { * @throws Drupal\Core\Database\ConnectionNotDefinedException * @throws Drupal\Core\Database\DriverNotSpecifiedException */ - final protected static function openConnection($key, $target) { + final protected static function openConnection($key, $target, $database_info = array()) { if (empty(self::$databaseInfo)) { - self::parseConnectionInfo(); + self::parseConnectionInfo($database_info); } // If the requested database does not exist then it is an unrecoverable diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php index 5d34a62..42eec41 100644 --- a/core/lib/Drupal/Core/Database/Install/Tasks.php +++ b/core/lib/Drupal/Core/Database/Install/Tasks.php @@ -19,6 +19,14 @@ */ abstract class Tasks { + protected $databases = array(); + + function __construct($database_info = NULL) { + if ($database_info) { + $this->databases['default']['default'] = $database_info; + } + } + /** * Structure that describes each task to run. * @@ -160,10 +168,7 @@ public function runTasks() { */ protected function connect() { try { - // This doesn't actually test the connection. - db_set_active(); - // Now actually do a check. - Database::getConnection(); + Database::getConnection('default', NULL, $this->databases); $this->pass('Drupal can CONNECT to the database ok.'); } catch (Exception $e) { diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index b31d8a0..bbac79c 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -710,13 +710,13 @@ protected function changeDatabasePrefix() { } Database::addConnectionInfo('default', 'default', $connection_info['default']); - // Additionally override global $databases, since the installer does not use + // Additionally set database.info, since the installer does not use // the Database connection info. // @see install_verify_database_settings() // @see install_database_errors() // @todo Fix installer to use Database connection info. - global $databases; $databases['default']['default'] = $connection_info['default']; + drupal_container()->setParameter('database.info', $databases); // Indicate the database prefix was set up correctly. $this->setupDatabasePrefix = TRUE; @@ -896,6 +896,9 @@ protected function tearDown() { $GLOBALS['theme_key'] = $this->originalThemeKey; $GLOBALS['theme'] = $this->originalTheme; + // Restore the original container. + drupal_container($this->originalContainer); + // Reset all static variables. drupal_static_reset(); @@ -907,7 +910,6 @@ protected function tearDown() { $conf = $this->originalConf; // Restore original statics and globals. - drupal_container($this->originalContainer); $language_interface = $this->originalLanguage; $GLOBALS['config_directories'] = $this->originalConfigDirectories; if (isset($this->originalPrefix)) { diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 400d885..23fae47 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -613,6 +613,8 @@ protected function setUp() { // Reset all statics and variables to perform tests in a clean environment. $conf = array(); drupal_static_reset(); + // drupal_container() does not use drupal_static(). + drupal_container(NULL, TRUE); // Change the database prefix. // All static variables need to be reset before the database prefix is diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php index 585a3ff..af9d218 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php @@ -8,6 +8,7 @@ namespace Drupal\system\Tests\Cache; use Drupal\Core\Cache\DatabaseBackend; +use Drupal\Core\Database\Database; /** * Tests DatabaseBackend using GenericCacheBackendUnitTestBase. @@ -23,7 +24,7 @@ public static function getInfo() { } protected function createCacheBackend($bin) { - return new DatabaseBackend($bin); + return new DatabaseBackend($bin, Database::getConnection()); } public function setUpCacheBackend() { diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php index 58078cd..73e7fdd 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\DatabaseBackend; use Drupal\Core\Cache\InstallBackend; +use Drupal\Core\Database\Database; use Exception; /** @@ -49,8 +50,8 @@ public static function getInfo() { * clearing various items in the cache. */ function testCacheInstall() { - $database_cache = new DatabaseBackend('test'); - $install_cache = new InstallBackend('test'); + $database_cache = new DatabaseBackend('test', Database::getConnection()); + $install_cache = new InstallBackend('test', Database::getConnection()); // Store an item in the database cache, and confirm that the installer's // cache backend recognizes that the cache is not empty. diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php index 65c30de..4acd3c8 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php @@ -7,6 +7,8 @@ namespace Drupal\system\Tests\Upgrade; +use Symfony\Component\DependencyInjection\Reference; + /** * Tests upgrading a filled database with language data. * diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php index c4c6f75..d9fe830 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModulesDisabledUpgradePathTest.php @@ -7,6 +7,8 @@ namespace Drupal\system\Tests\Upgrade; +use Symfony\Component\DependencyInjection\Reference; + /** * Tests upgrading with all non-required modules installed but disabled. * diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php index 6598e06..df698df 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php @@ -7,10 +7,10 @@ namespace Drupal\system\Tests\Upgrade; -use Drupal\Core\Database\Database; use Drupal\simpletest\WebTestBase; use Exception; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; /** * Perform end-to-end tests of the upgrade path. @@ -239,6 +239,12 @@ protected function performUpgrade($register_errors = TRUE) { // of the child site directly from this request. $this->upgradedSite = TRUE; + $container = drupal_container(); + foreach (array('block', 'field', 'filter', 'path', 'form', 'menu') as $bin) { + $definition = clone $container->getDefinition('cache'); + $container->setDefinition('cache.' . $bin, $definition->replaceArgument(0, $bin)); + } + // Reload module list for modules that are enabled in the test database // but not on the test client. system_list_reset(); diff --git a/core/modules/system/system.install b/core/modules/system/system.install index e138f32..0a4e09e 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -184,7 +184,7 @@ function system_requirements($phase) { else { // Database information. $class = Database::getConnection()->getDriverClass('Install\\Tasks'); - $tasks = new $class(); + $tasks = new $class(drupal_container()->getParameter('database.info')); $requirements['database_system'] = array( 'title' => $t('Database system'), 'value' => $tasks->name(), diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 2395a84..40f4647 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -4,6 +4,8 @@ * This script runs Drupal tests from command line. */ +use Drupal\Core\DrupalKernel; + const SIMPLETEST_SCRIPT_COLOR_PASS = 32; // Green. const SIMPLETEST_SCRIPT_COLOR_FAIL = 31; // Red. const SIMPLETEST_SCRIPT_COLOR_EXCEPTION = 33; // Brown. @@ -371,6 +373,10 @@ function simpletest_script_run_one_test($test_id, $test_class) { // Bootstrap Drupal. drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + // Initialize and boot the kernel to get a fully loaded container. + $kernel = new DrupalKernel('prod', FALSE); + $kernel->boot(); + simpletest_classloader_register(); // Override configuration according to command line parameters. diff --git a/core/update.php b/core/update.php index 2273b40..e187a1f 100644 --- a/core/update.php +++ b/core/update.php @@ -268,7 +268,13 @@ function update_info_page() { _drupal_flush_css_js(); // Flush the cache of all data for the update status module. if (db_table_exists('cache_update')) { - cache('update')->flush(); + $query = db_delete('cache_update'); + $query->condition( + db_or() + ->condition('cid', 'update_project_%', 'LIKE') + ->condition('cid', 'available_releases::%', 'LIKE') + ); + $query->execute(); } update_task_list('info'); @@ -448,15 +454,16 @@ function update_check_requirements($skip_warnings = FALSE) { // @todo Remove after converting update.php to use DrupalKernel. $container = drupal_container(); -$container->register('database', 'Drupal\Core\Database\Connection') - ->setFactoryClass('Drupal\Core\Database\Database') - ->setFactoryMethod('getConnection') - ->addArgument('default'); $container->register('router.dumper', '\Drupal\Core\Routing\MatcherDumper') ->addArgument(new Reference('database')); $container->register('router.builder', 'Drupal\Core\Routing\RouteBuilder') ->addArgument(new Reference('router.dumper')); +foreach (array('block', 'field', 'filter', 'path', 'form', 'menu') as $bin) { + $definition = clone $container->getDefinition('cache'); + $container->setDefinition('cache.' . $bin, $definition->replaceArgument(0, $bin)); +} + // Turn error reporting back on. From now on, only fatal errors (which are // not passed through the error handler) will cause a message to be printed. ini_set('display_errors', TRUE);