diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index b667d89..98f5922 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -3,7 +3,9 @@ use Drupal\Core\Database\Database; use Symfony\Component\ClassLoader\UniversalClassLoader; use Symfony\Component\ClassLoader\ApcUniversalClassLoader; -use Drupal\Core\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Drupal\Core\Language\Language; @@ -1473,7 +1475,7 @@ function t($string, array $args = array(), array $options = array()) { // Merge in default. if (empty($options['langcode'])) { - $options['langcode'] = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + $options['langcode'] = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode; } if (empty($options['context'])) { $options['context'] = ''; @@ -1628,29 +1630,6 @@ function request_uri($omit_query_string = FALSE) { } /** - * Returns the current global request object. - * - * @todo Replace this function with a proper dependency injection container. - * - * @staticvar Symfony\Component\HttpFoundation\Request $request - * - * @param Symfony\Component\HttpFoundation\Request $new_request - * Optional. The new request object to store. This parameter should only be - * used by index.php. - * - * @return Symfony\Component\HttpFoundation\Request - * The current request object. - */ -function request(Request $new_request = NULL) { - static $request; - - if ($new_request) { - $request = $new_request; - } - return $request; -} - -/** * Logs an exception. * * This is a wrapper function for watchdog() which automatically decodes an @@ -2455,28 +2434,23 @@ function drupal_get_bootstrap_phase() { /** * Retrieves the Drupal Container to standardize object construction. * - * Example: - * @code - * // Register the LANGUAGE_TYPE_INTERFACE definition. Registered definitions - * // do not necessarily need to be named by a constant. - * // See - * // http://symfony.com/doc/current/components/dependency_injection/introduction.html - * // for usage examples of adding object initialization code after register(). - * $container = drupal_container(); - * $container->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language'); - * - * // Retrieve the LANGUAGE_TYPE_INTERFACE object. - * $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); - * @endcode + * On a normal page request the container is built by the kernel and passed in + * to this function which stores it statically. Any full bootstrap outside of + * the context of a page request will require a container with a minimal set of + * services. If this function is called without the $reset parameter, and no + * container object has been statically cached, it builds this minimal container, + * registering the services that are required. + * + * @see Drupal\Core\DrupalKernel * * @param $reset * A new container instance to reset the Drupal container to. * - * @return Drupal\Component\DependencyInjection\ContainerBuilder - * The instance of the Drupal Container used to set up and maintain object + * @return Symfony\Component\DependencyInjection\Container + * The instance of the Container used to set up and maintain object * instances. */ -function drupal_container(ContainerBuilder $reset = NULL) { +function drupal_container(Container $reset = NULL) { // We do not use drupal_static() here because we do not have a mechanism by // which to reinitialize the stored objects, so a drupal_static_reset() call // would leave Drupal in a nonfunctional state. @@ -2485,7 +2459,31 @@ function drupal_container(ContainerBuilder $reset = NULL) { $container = $reset; } elseif (!isset($container)) { + // Return a ContainerBuilder instance with the bare essentials needed for any + // full bootstrap regardless of whether there will be a DrupalKernel involved. + // This will get merged with the full Kernel-built Container on normal page + // requests. $container = new ContainerBuilder(); + // Register configuration storage dispatcher. + $container->setParameter('config.storage.info', array( + 'Drupal\Core\Config\DatabaseStorage' => array( + 'connection' => 'default', + 'target' => 'default', + 'read' => TRUE, + 'write' => TRUE, + ), + 'Drupal\Core\Config\FileStorage' => array( + 'directory' => config_get_config_directory(), + 'read' => TRUE, + 'write' => FALSE, + ), + )); + $container->register('config.storage.dispatcher', 'Drupal\Core\Config\StorageDispatcher') + ->addArgument('%config.storage.info%'); + + // Register configuration object factory. + $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') + ->addArgument(new Reference('config.storage.dispatcher')); } return $container; } @@ -2633,34 +2631,67 @@ function get_t() { /** * Initializes all the defined language types. * - * @see Drupal\Core\Language\Language + * @see language_manager() */ function drupal_language_initialize() { - $types = language_types_get_all(); - $container = drupal_container(); - - // Ensure a language object is registered for each language type, whether the - // site is multilingual or not. if (language_multilingual()) { - include_once DRUPAL_ROOT . '/core/includes/language.inc'; + $types = language_types_get_all(); foreach ($types as $type) { - $language = language_types_initialize($type); - $container->set($type, NULL); - $container->register($type, 'Drupal\\Core\\Language\\Language') - ->addMethodCall('extend', array($language)); + language_manager($type); } // Allow modules to react on language system initialization in multilingual // environments. bootstrap_invoke_all('language_init'); } - else { - $default = language_default(); - foreach ($types as $type) { - $container->set($type, NULL); - $container->register($type, 'Drupal\\Core\\Language\\Language') - ->addMethodCall('extend', array($default)); +} + +/** + * Initializes the passed in language type. + * + * The 'language_manager' service is only available within the scope of a kernel + * request. When it's not available, we return a default language object, + * regardless of the type passed in. + * + * Note that this function is provided for legacy code that needs to get e.g. + * the interface language outside the scope of a request. Code that runs within + * the scope of a request should call + * drupal_container()->get('language_manager')->getLanguage($type) + * directly. + * + * @see Drupal\Core\Language\LanguageManager + */ +function language_manager($type = NULL) { + // Keep track of whether we are in a multilingual environment. + static $multilingual = FALSE; + // Keep track of whether the language_manager service is available. + static $language_manager_service = FALSE; + if ($multilingual && $language_manager_service) { + if (!$type) { + drupal_container()->get('language_manager')->reset(); + return; + } + return drupal_container()->get('language_manager')->getLanguage($type); + } + if (language_multilingual()) { + $multilingual = TRUE; + if (drupal_container()->has('language_manager')) { + $language_manager_service = TRUE; + return drupal_container()->get('language_manager')->getLanguage($type); } } + // We can't use drupal_static() here because resetting is not a simple case of + // drupal_static_reset(). + static $languages; + // If no type was passed in, reset the languages array. + if (!$type) { + $languages = array(); + } + // If this is not a multilingual environment or we have not yet entered the + // request scope, just use the default language regardless of $type. + if (!isset($languages[$type])) { + $languages[$type] = language_default(); + } + return $languages[$type]; } /** diff --git a/core/includes/common.inc b/core/includes/common.inc index e57efb9..cd56aa1 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1597,7 +1597,7 @@ function filter_xss_bad_protocol($string, $decode = TRUE) { * Arbitrary elements may be added using the $args associative array. */ function format_rss_channel($title, $link, $description, $items, $langcode = NULL, $args = array()) { - $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = $langcode ? $langcode : language_manager(LANGUAGE_TYPE_CONTENT)->langcode; $output = "\n"; $output .= ' ' . check_plain($title) . "\n"; @@ -1899,7 +1899,7 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL } if (empty($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode; } switch ($type) { @@ -2075,7 +2075,7 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) { * - 'language': An optional language object. If the path being linked to is * internal to the site, $options['language'] is used to look up the alias * for the URL. If $options['language'] is omitted, the language will be - * obtained from drupal_container()->get(LANGUAGE_TYPE_URL). + * obtained from language_manager(LANGUAGE_TYPE_URL). * - 'https': Whether this URL should point to a secure location. If not * defined, the current scheme is used, so the user stays on http or https * respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can @@ -2324,7 +2324,7 @@ function l($text, $path, array $options = array()) { // Append active class. if (($path == current_path() || ($path == '' && drupal_is_front_page())) && - (empty($options['language']) || $options['language']->langcode == drupal_container()->get(LANGUAGE_TYPE_URL)->langcode)) { + (empty($options['language']) || $options['language']->langcode == language_manager(LANGUAGE_TYPE_URL)->langcode)) { $options['attributes']['class'][] = 'active'; } @@ -4914,9 +4914,9 @@ function _drupal_bootstrap_code() { } /** - * Temporary BC function for scripts not using HttpKernel. + * Temporary BC function for scripts not using DrupalKernel. * - * HttpKernel skips this and replicates it via event listeners. + * DrupalKernel skips this and replicates it via event listeners. * * @see Drupal\Core\EventSubscriber\PathSubscriber; * @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; @@ -6012,7 +6012,7 @@ function drupal_render_cid_parts($granularity = NULL) { // part. if (language_multilingual()) { foreach (language_types_get_configurable() as $language_type) { - $cid_parts[] = drupal_container()->get($language_type)->langcode; + $cid_parts[] = language_manager($language_type)->langcode; } } diff --git a/core/includes/form.inc b/core/includes/form.inc index 0c9cd5d..7498ea5 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1267,7 +1267,7 @@ function drupal_redirect_form($form_state) { $function($form_state['redirect']); } } - drupal_goto(current_path(), array('query' => request()->query->all())); + drupal_goto(current_path(), array('query' => drupal_container()->get('request')->query->all())); } } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index a112b5e..67d2a5f 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1,5 +1,6 @@ boot(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); } diff --git a/core/includes/language.inc b/core/includes/language.inc index 0892cc4..48ba3d6 100644 --- a/core/includes/language.inc +++ b/core/includes/language.inc @@ -110,7 +110,7 @@ const LANGUAGE_NEGOTIATION_DEFAULT = 'language-default'; * @return * The negotiated language object. */ -function language_types_initialize($type) { +function language_types_initialize($type, $args = array()) { // Execute the language negotiation methods in the order they were set up and // return the first valid language found. $negotiation = variable_get("language_negotiation_$type", array()); @@ -120,6 +120,7 @@ function language_types_initialize($type) { if (isset($method['types']) && !in_array($type, $method['types'])) { continue; } + $method['args'] = $args; $language = language_negotiation_method_invoke($method_id, $method); if ($language) { // Remember the method ID used to detect the language. @@ -452,7 +453,8 @@ function language_negotiation_method_invoke($method_id, $method = NULL) { // satisfied we can execute the callback. $cache = !isset($method['cache']) || $user->uid || $method['cache'] == variable_get('cache', 0); $callback = isset($method['callbacks']['negotiation']) ? $method['callbacks']['negotiation'] : FALSE; - $langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE; + $args = isset($method['args']) ? $method['args'] : array(); + $langcode = $cache && function_exists($callback) ? $callback($languages, $args) : FALSE; $results[$method_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE; } diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 1dad781..c679895 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -1069,7 +1069,7 @@ function menu_tree_output($tree) { */ function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) { $tree = &drupal_static(__FUNCTION__, array()); - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Use $mlid as a flag for whether the data being loaded is for the whole tree. $mlid = isset($link['mlid']) ? $link['mlid'] : 0; @@ -1180,7 +1180,7 @@ function menu_tree_get_path($menu_name) { function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = FALSE) { $tree = &drupal_static(__FUNCTION__, array()); - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Check if the active trail has been overridden for this menu tree. $active_path = menu_tree_get_path($menu_name); @@ -1336,7 +1336,7 @@ function menu_build_tree($menu_name, array $parameters = array()) { function _menu_build_tree($menu_name, array $parameters = array()) { // Static cache of already built menu trees. $trees = &drupal_static(__FUNCTION__, array()); - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Build the cache id; sort parents to prevent duplicate storage and remove // default parameter values. diff --git a/core/includes/path.inc b/core/includes/path.inc index 62a58a6..67fc5d9 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -82,7 +82,7 @@ function drupal_lookup_path($action, $path = '', $langcode = NULL) { // language. If we used a language different from the one conveyed by the // requested URL, we might end up being unable to check if there is a path // alias matching the URL path. - $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_URL)->langcode; + $langcode = $langcode ? $langcode : language_manager(LANGUAGE_TYPE_URL)->langcode; if ($action == 'wipe') { $cache = array(); @@ -213,6 +213,17 @@ function drupal_cache_system_paths() { // request to avoid writing to cache on every request. $cache = &drupal_static('drupal_lookup_path', array()); if (empty($cache['system_paths']) && !empty($cache['map'])) { + + // @todo Because caching happens during $kernel->terminate(), i.e. + // after we have left the scope of the Request, the call to current_path() + // here does not return the system path, and instead calls out to + // _current_path(), which returns the alias. So the alias gets used as the + // key instead. At lookup time, whether the alias or the source is used as + // the key depends on when the first call to url() is made for that path. + // If this is within the request scope, it uses the system_path and so will + // be a cache miss. There is a separate issue for fixing up the path alias + // logic here: http://drupal.org/node/1269742 + // Generate a cache ID (cid) specifically for this page. $cid = current_path(); // The static $map array used by drupal_lookup_path() includes all @@ -358,6 +369,11 @@ function drupal_match_path($path, $patterns) { * @see request_path() */ function current_path() { + if (drupal_container()->has('request')) { + return drupal_container()->get('request')->attributes->get('system_path'); + } + // If we are outside the request scope, e.g. during $kernel->terminate, fall + // back to using the path stored in _current_path(). return _current_path(); } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 84e2ec7..9c4306a 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1624,7 +1624,7 @@ function theme_link($variables) { * http://www.w3.org/TR/WCAG-TECHS/H42.html for more information. */ function theme_links($variables) { - $language_url = drupal_container()->get(LANGUAGE_TYPE_URL); + $language_url = language_manager(LANGUAGE_TYPE_URL); $links = $variables['links']; $attributes = $variables['attributes']; @@ -2419,7 +2419,7 @@ function template_process(&$variables, $hook) { * @see html.tpl.php */ function template_preprocess_html(&$variables) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Compile a list of classes that are going to be applied to the body element. // This allows advanced theming based on context (home page, node of certain type, etc.). @@ -2550,7 +2550,7 @@ function template_preprocess_html(&$variables) { * @see page.tpl.php */ function template_preprocess_page(&$variables) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $site_config = config('system.site'); // Move some variables to the top level for themer convenience and template cleanliness. @@ -2735,7 +2735,7 @@ function theme_get_suggestions($args, $base, $delimiter = '__') { */ function template_preprocess_maintenance_page(&$variables) { global $theme; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Retrieve the theme data to list all available regions. $theme_data = list_themes(); $regions = $theme_data[$theme]->info['regions']; diff --git a/core/includes/update.inc b/core/includes/update.inc index 5aff2bc..0902036 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -247,8 +247,10 @@ function update_prepare_d8_language() { // Update the 'language_default' system variable, if configured. $language_default = variable_get('language_default'); - if (!empty($language_default) && isset($language_default->language)) { - $language_default->langcode = $language_default->language; + if (!empty($language_default) && (isset($language_default->langcode) || isset($language_default->language))) { + if (!isset($language_default->langcode)) { + $language_default->langcode = $language_default->language; + } unset($language_default->language); // In D8, the 'language_default' is not anymore an object, but an array, // so make sure that the new value that is saved into this variable is an diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php new file mode 100644 index 0000000..dba824f --- /dev/null +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -0,0 +1,85 @@ +addScope(new Scope('request')); + + $container->register('dispatcher', 'Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher') + ->addArgument(new Reference('service_container')); + $container->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); + $container->register('http_kernel', 'Drupal\Core\HttpKernel') + ->addArgument(new Reference('dispatcher')) + ->addArgument(new Reference('service_container')) + ->addArgument(new Reference('resolver')); + $container->register('matcher', 'Drupal\Core\LegacyUrlMatcher'); + $container->register('router_listener', 'Drupal\Core\EventSubscriber\RouterListener') + ->addArgument(new Reference('matcher')) + ->addTag('kernel.event_subscriber'); + $container->register('content_negotiation', 'Drupal\Core\ContentNegotiation'); + $container->register('view_subscriber', 'Drupal\Core\EventSubscriber\ViewSubscriber') + ->addArgument(new Reference('content_negotiation')) + ->addTag('kernel.event_subscriber'); + $container->register('access_subscriber', 'Drupal\Core\EventSubscriber\AccessSubscriber') + ->addTag('kernel.event_subscriber'); + $container->register('maintenance_mode_subscriber', 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber') + ->addTag('kernel.event_subscriber'); + $container->register('path_subscriber', 'Drupal\Core\EventSubscriber\PathSubscriber') + ->addTag('kernel.event_subscriber'); + $container->register('legacy_request_subscriber', 'Drupal\Core\EventSubscriber\LegacyRequestSubscriber') + ->addTag('kernel.event_subscriber'); + $container->register('legacy_controller_subscriber', 'Drupal\Core\EventSubscriber\LegacyControllerSubscriber') + ->addTag('kernel.event_subscriber'); + $container->register('finish_response_subscriber', 'Drupal\Core\EventSubscriber\FinishResponseSubscriber') + ->addArgument(new Reference('language_manager')) + ->setScope('request') + ->addTag('kernel.event_subscriber'); + $container->register('request_close_subscriber', 'Drupal\Core\EventSubscriber\RequestCloseSubscriber') + ->addTag('kernel.event_subscriber'); + $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'); + $container->register('exception_listener', 'Symfony\Component\HttpKernel\EventListener\ExceptionListener') + ->addTag('kernel.event_subscriber') + ->addArgument(new Reference('service_container')) + ->setFactoryClass('Drupal\Core\ExceptionController') + ->setFactoryMethod('getExceptionListener'); + $container->register('request', 'Symfony\Component\HttpFoundation\Request') + ->setSynthetic(TRUE); + $container->register('language_manager', 'Drupal\Core\Language\LanguageManager') + ->addArgument(new Reference('request')) + ->setScope('request'); + + // Add a compiler pass for registering event subscribers. + $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING); + } +} diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php new file mode 100644 index 0000000..5b1a9ab --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php @@ -0,0 +1,38 @@ +hasDefinition('dispatcher')) { + return; + } + + $definition = $container->getDefinition('dispatcher'); + + foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) { + + // We must assume that the class value has been correcly filled, even if the service is created by a factory + $class = $container->getDefinition($id)->getClass(); + + $refClass = new ReflectionClass($class); + $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + if (!$refClass->implementsInterface($interface)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + } + $definition->addMethodCall('addSubscriberService', array($id, $class)); + } + } +} diff --git a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php index a82f5b6..dfccb74 100644 --- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php +++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php @@ -7,113 +7,29 @@ namespace Drupal\Core\DependencyInjection; -use Drupal\Core\ContentNegotiation; -use Drupal\Core\EventSubscriber\AccessSubscriber; -use Drupal\Core\EventSubscriber\FinishResponseSubscriber; -use Drupal\Core\EventSubscriber\LegacyControllerSubscriber; -use Drupal\Core\EventSubscriber\LegacyRequestSubscriber; -use Drupal\Core\EventSubscriber\MaintenanceModeSubscriber; -use Drupal\Core\EventSubscriber\PathSubscriber; -use Drupal\Core\EventSubscriber\RequestCloseSubscriber; -use Drupal\Core\EventSubscriber\RouterListener; -use Drupal\Core\EventSubscriber\ViewSubscriber; -use Drupal\Core\ExceptionController; -use Drupal\Core\LegacyUrlMatcher; use Symfony\Component\DependencyInjection\ContainerBuilder as BaseContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\HttpKernel\EventListener\ExceptionListener; +use Symfony\Component\DependencyInjection\Compiler\Compiler; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** * Drupal's dependency injection container. */ class ContainerBuilder extends BaseContainerBuilder { - /** - * Registers the base Drupal services for the dependency injection container. - */ public function __construct() { parent::__construct(); - - // An interface language always needs to be available for t() and other - // functions. This default is overridden by drupal_language_initialize() - // during language negotiation. - $this->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language'); - - // Register the default language content. - $this->register(LANGUAGE_TYPE_CONTENT, 'Drupal\\Core\\Language\\Language'); - - // Register configuration storage dispatcher. - $this->setParameter('config.storage.info', array( - 'Drupal\Core\Config\DatabaseStorage' => array( - 'connection' => 'default', - 'target' => 'default', - 'read' => TRUE, - 'write' => TRUE, - ), - 'Drupal\Core\Config\FileStorage' => array( - 'directory' => config_get_config_directory(), - 'read' => TRUE, - 'write' => FALSE, - ), - )); - $this->register('config.storage.dispatcher', 'Drupal\Core\Config\StorageDispatcher') - ->addArgument('%config.storage.info%'); - - // Register configuration object factory. - $this->register('config.factory', 'Drupal\Core\Config\ConfigFactory') - ->addArgument(new Reference('config.storage.dispatcher')); - - // Register the HTTP kernel services. - $this->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher') - ->addArgument(new Reference('service_container')) - ->setFactoryClass('Drupal\Core\DependencyInjection\ContainerBuilder') - ->setFactoryMethod('getKernelEventDispatcher'); - $this->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); - $this->register('httpkernel', 'Symfony\Component\HttpKernel\HttpKernel') - ->addArgument(new Reference('dispatcher')) - ->addArgument(new Reference('resolver')); + $this->compiler = new Compiler(); } - /** - * Creates an EventDispatcher for the HttpKernel. Factory method. - * - * @param Drupal\Core\DependencyInjection\ContainerBuilder $container - * The dependency injection container that contains the HTTP kernel. - * - * @return Symfony\Component\EventDispatcher\EventDispatcher - * An EventDispatcher with the default listeners attached to it. - */ - public static function getKernelEventDispatcher($container) { - $dispatcher = new EventDispatcher(); - - $matcher = new LegacyUrlMatcher(); - $dispatcher->addSubscriber(new RouterListener($matcher)); - - $negotiation = new ContentNegotiation(); - - // @todo Make this extensible rather than just hard coding some. - // @todo Add a subscriber to handle other things, too, like our Ajax - // replacement system. - $dispatcher->addSubscriber(new ViewSubscriber($negotiation)); - $dispatcher->addSubscriber(new AccessSubscriber()); - $dispatcher->addSubscriber(new MaintenanceModeSubscriber()); - $dispatcher->addSubscriber(new PathSubscriber()); - $dispatcher->addSubscriber(new LegacyRequestSubscriber()); - $dispatcher->addSubscriber(new LegacyControllerSubscriber()); - $dispatcher->addSubscriber(new FinishResponseSubscriber()); - $dispatcher->addSubscriber(new RequestCloseSubscriber()); - - // Some other form of error occured that wasn't handled by another kernel - // listener. That could mean that it's a method/mime-type/error combination - // that is not accounted for, or some other type of error. Either way, treat - // it as a server-level error and return an HTTP 500. By default, this will - // be an HTML-type response because that's a decent best guess if we don't - // know otherwise. - $exceptionController = new ExceptionController($negotiation); - $exceptionController->setContainer($container); - $dispatcher->addSubscriber(new ExceptionListener(array($exceptionController, 'execute'))); + public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { + $this->compiler->addPass($pass, $type); + } - return $dispatcher; + public function compile() { + $this->compiler->compile($this); + $this->parameterBag->resolve(); } + } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php new file mode 100644 index 0000000..6737310 --- /dev/null +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -0,0 +1,92 @@ +container = $this->buildContainer(); + $this->container->set('kernel', $this); + drupal_container($this->container); + } + + /** + * Builds the service container. + * + * @return ContainerBuilder The compiled service container + */ + protected function buildContainer() { + $container = $this->getContainerBuilder(); + + // Merge in the minimal bootstrap container. + if ($bootstrap_container = drupal_container()) { + $container->merge($bootstrap_container); + } + foreach ($this->bundles as $bundle) { + $bundle->build($container); + } + $container->compile(); + return $container; + } + + /** + * Gets a new ContainerBuilder instance used to build the service container. + * + * @return ContainerBuilder + */ + protected function getContainerBuilder() { + return new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + } + + /** + * Overrides and eliminates this method from the parent class. Do not use. + * + * This method is part of the KernelInterface interface, but takes an object + * implementing LoaderInterface as its only parameter. This is part of the + * Config compoment from Symfony, which is not provided by Drupal core. + * + * Modules wishing to provide an extension to this class which uses this + * method are responsible for ensuring the Config component exists. + */ + public function registerContainerConfiguration(LoaderInterface $loader) { + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 6e23845..3c3126d 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -7,6 +7,7 @@ namespace Drupal\Core\EventSubscriber; +use Drupal\Core\Language\LanguageManager; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -16,6 +17,12 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; */ class FinishResponseSubscriber implements EventSubscriberInterface { + protected $language_manager; + + public function __construct(LanguageManager $language_manager) { + $this->language_manager = $language_manager; + } + /** * Sets extra headers on successful responses. * @@ -30,7 +37,7 @@ class FinishResponseSubscriber implements EventSubscriberInterface { $response->headers->set('X-UA-Compatible', 'IE=edge,chrome=1', false); // Set the Content-language header. - $response->headers->set('Content-language', drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode); + $response->headers->set('Content-language', $this->language_manager->getLanguage(LANGUAGE_TYPE_INTERFACE)->langcode); // Because pages are highly dynamic, set the last-modified time to now // since the page is in fact being regenerated right now. diff --git a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php index fd0a765..385798c 100644 --- a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php +++ b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php @@ -21,9 +21,5 @@ abstract class PathListenerBase { public function setPath(Request $request, $path) { $request->attributes->set('system_path', $path); - - // @todo Remove this line once code has been refactored to use the request - // object directly. - _current_path($path); } } diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php index 2e1bece..7688107 100644 --- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php @@ -69,9 +69,6 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac * The Event to process. */ public function onKernelRequestLanguageResolve(GetResponseEvent $event) { - $request = $event->getRequest(); - $path = $this->extractPath($request); - // drupal_language_initialize() combines: // - Determination of language from $request information (e.g., path). // - Determination of language from other information (e.g., site default). @@ -80,11 +77,7 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac // @todo Decouple the above, but for now, invoke it and update the path // prior to front page and alias resolution. When above is decoupled, also // add 'langcode' (determined from $request only) to $request->attributes. - _current_path($path); drupal_language_initialize(); - $path = _current_path(); - - $this->setPath($request, $path); } /** diff --git a/core/lib/Drupal/Core/ExceptionController.php b/core/lib/Drupal/Core/ExceptionController.php index 7f71e28..e302671 100644 --- a/core/lib/Drupal/Core/ExceptionController.php +++ b/core/lib/Drupal/Core/ExceptionController.php @@ -7,12 +7,14 @@ namespace Drupal\Core; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\HttpKernel; +use Drupal\Core\HttpKernel; use Symfony\Component\HttpKernel\Exception\FlattenException; +use Symfony\Component\HttpKernel\EventListener\ExceptionListener; /** * This controller handles HTTP errors generated by the routing system. @@ -27,6 +29,24 @@ class ExceptionController extends ContainerAware { protected $negotiation; /** + * Instantiates a new exception listener. + * + * Factory method for getting an Exception Listener. Since this needs to be + * instanciated with a controller callable, i.e. an ExceptionConroller object + * and the name of the method to call, we can't just register it to the DIC + * the regular way. + * + * @todo: This probably doesn't belong here, but I'm not sure where would be a better + * place to put it... in a class of its own? + */ + public static function getExceptionListener(Container $container) { + $negotiation = $container->get('content_negotiation'); + $exceptionController = new self($negotiation); + $exceptionController->setContainer($container); + return new ExceptionListener(array($exceptionController, 'execute')); + } + + /** * Constructor. * * @param Drupal\Core\ContentNegotiation $negotiation @@ -107,7 +127,7 @@ class ExceptionController extends ContainerAware { drupal_static_reset('menu_set_active_trail'); menu_reset_static_cache(); - $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST); + $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST); $response->setStatusCode(403, 'Access denied'); } else { @@ -172,7 +192,7 @@ class ExceptionController extends ContainerAware { drupal_static_reset('menu_set_active_trail'); menu_reset_static_cache(); - $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST); + $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST); $response->setStatusCode(404, 'Not Found'); } else { diff --git a/core/lib/Drupal/Core/HttpKernel.php b/core/lib/Drupal/Core/HttpKernel.php new file mode 100644 index 0000000..d8031f3 --- /dev/null +++ b/core/lib/Drupal/Core/HttpKernel.php @@ -0,0 +1,51 @@ +container = $container; + } + + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) + { + $request->headers->set('X-Php-Ob-Level', ob_get_level()); + + $this->container->enterScope('request'); + $this->container->set('request', $request, 'request'); + + try { + $response = parent::handle($request, $type, $catch); + } catch (\Exception $e) { + $this->container->leaveScope('request'); + + throw $e; + } + + $this->container->leaveScope('request'); + + return $response; + } +} diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php new file mode 100644 index 0000000..7bc7606 --- /dev/null +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -0,0 +1,43 @@ +request = $request; + } + + public function getLanguage($type) { + if (isset($this->languages[$type])) { + return $this->languages[$type]; + } + + // @todo Objectify the language system so that we don't have to do this. + include_once DRUPAL_ROOT . '/core/includes/language.inc'; + $this->languages[$type] = language_types_initialize($type, array('request' => $this->request)); + return $this->languages[$type]; + } + + function reset() { + $this->languages = array(); + } +} diff --git a/core/modules/aggregator/aggregator.admin.inc b/core/modules/aggregator/aggregator.admin.inc index 7bb4c04..718e79c 100644 --- a/core/modules/aggregator/aggregator.admin.inc +++ b/core/modules/aggregator/aggregator.admin.inc @@ -412,7 +412,7 @@ function aggregator_admin_refresh_feed($feed) { // @todo CSRF tokens are validated in page callbacks rather than access // callbacks, because access callbacks are also invoked during menu link // generation. Add token support to routing: http://drupal.org/node/755584. - $token = request()->query->get('token'); + $token = drupal_container()->get('request')->query->get('token'); if (!isset($token) || !drupal_valid_token($token, 'aggregator/update/' . $feed->fid)) { throw new AccessDeniedHttpException(); } diff --git a/core/modules/block/block.api.php b/core/modules/block/block.api.php index 9fee858..bf166c9 100644 --- a/core/modules/block/block.api.php +++ b/core/modules/block/block.api.php @@ -329,7 +329,7 @@ function hook_block_view_MODULE_DELTA_alter(&$data, $block) { */ function hook_block_list_alter(&$blocks) { global $theme_key; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // This example shows how to achieve language specific visibility setting for // blocks. diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 455f98f..8ff6308 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -880,7 +880,7 @@ function block_block_list_alter(&$blocks) { continue; } foreach ($block_langcodes[$block->module][$block->delta] as $language_type => $langcodes) { - if (isset($langcodes[drupal_container()->get($language_type)->langcode])) { + if (isset($langcodes[language_manager($language_type)->langcode])) { // Found a language type - langcode combination in the configuration // that is applicable to the current request. continue 2; diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 40802a1..b3fdc25 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -1224,7 +1224,7 @@ function book_toc($bid, $depth_limit, $exclude = array()) { */ function template_preprocess_book_export_html(&$variables) { global $base_url; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $variables['title'] = check_plain($variables['title']); $variables['base_url'] = $base_url; diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 0a7b261..4cf96d3 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -504,12 +504,12 @@ function comment_permalink($cid) { $page = comment_get_display_page($comment->cid, $node->type); // @todo: Cleaner sub request handling. - $subrequest = Request::create('/node/' . $node->nid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all()); + $request = drupal_container()->get('request'); + $subrequest = Request::create('/node/' . $node->nid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all()); $subrequest->query->set('page', $page); // @todo: Convert the pager to use the request object. $_GET['page'] = $page; - request($subrequest); - return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); + return drupal_container()->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); } throw new NotFoundHttpException(); } @@ -958,7 +958,7 @@ function comment_prepare_thread(&$comments) { */ function comment_view(Comment $comment, Node $node, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Populate $comment->content with a render() array. @@ -1024,7 +1024,7 @@ function comment_view(Comment $comment, Node $node, $view_mode = 'full', $langco */ function comment_build_content(Comment $comment, Node $node, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Remove previously built content, if exists. @@ -1682,7 +1682,7 @@ function comment_forms() { */ function comment_form($form, &$form_state, Comment $comment) { global $user; - $language_content = drupal_container()->get(LANGUAGE_TYPE_CONTENT); + $language_content = language_manager(LANGUAGE_TYPE_CONTENT); // During initial form build, add the comment entity to the form state for // use during form building and processing. During a rebuild, use what is in diff --git a/core/modules/comment/comment.pages.inc b/core/modules/comment/comment.pages.inc index 3167bd7..ae50379 100644 --- a/core/modules/comment/comment.pages.inc +++ b/core/modules/comment/comment.pages.inc @@ -116,7 +116,7 @@ function comment_approve($cid) { // @todo CSRF tokens are validated in page callbacks rather than access // callbacks, because access callbacks are also invoked during menu link // generation. Add token support to routing: http://drupal.org/node/755584. - $token = request()->query->get('token'); + $token = drupal_container()->get('request')->query->get('token'); if (!isset($token) || !drupal_valid_token($token, "comment/$cid/approve")) { throw new AccessDeniedHttpException(); } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php index aea41ef..50a7b55 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php @@ -23,7 +23,7 @@ class CommentTokenReplaceTest extends CommentTestBase { * Creates a comment, then tests the tokens generated from it. */ function testCommentTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $url_options = array( 'absolute' => TRUE, 'language' => $language_interface, diff --git a/core/modules/contact/contact.pages.inc b/core/modules/contact/contact.pages.inc index d20d79a..ed52c32 100644 --- a/core/modules/contact/contact.pages.inc +++ b/core/modules/contact/contact.pages.inc @@ -149,7 +149,7 @@ function contact_site_form_validate($form, &$form_state) { */ function contact_site_form_submit($form, &$form_state) { global $user; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $values = $form_state['values']; $values['sender'] = $user; @@ -290,7 +290,7 @@ function contact_personal_form($form, &$form_state, $recipient) { */ function contact_personal_form_submit($form, &$form_state) { global $user; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $values = $form_state['values']; $values['sender'] = $user; diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index a66b1e8..1a45276 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -46,7 +46,7 @@ function entity_modules_disabled() { * @see hook_entity_info_alter() */ function entity_get_info($entity_type = NULL) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Use the advanced drupal_static() pattern, since this is called very often. static $drupal_static_fast; diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc index 5ec5ed9..0f04c56 100644 --- a/core/modules/field/field.info.inc +++ b/core/modules/field/field.info.inc @@ -67,7 +67,7 @@ function field_info_cache_clear() { * @see _field_info_collate_types_reset() */ function _field_info_collate_types() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Use the advanced drupal_static() pattern, since this is called very often. static $drupal_static_fast; diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc index 17d385e..533c881 100644 --- a/core/modules/field/field.multilingual.inc +++ b/core/modules/field/field.multilingual.inc @@ -258,7 +258,7 @@ function field_valid_language($langcode, $default = TRUE) { if (in_array($langcode, $languages)) { return $langcode; } - return $default ? language_default()->langcode : drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + return $default ? language_default()->langcode : language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } /** diff --git a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php index 57e9a1e..c7df161 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php @@ -23,7 +23,7 @@ class FileTokenReplaceTest extends FileFieldTestBase { * Creates a file, then tests the tokens generated from it. */ function testFileTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $url_options = array( 'absolute' => TRUE, 'language' => $language_interface, diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 0e2f8d4..dc57eeb 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -399,7 +399,7 @@ function filter_modules_disabled($modules) { * @see filter_formats_reset() */ function filter_formats($account = NULL) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $formats = &drupal_static(__FUNCTION__, array()); // All available formats are cached for performance. diff --git a/core/modules/image/image.module b/core/modules/image/image.module index aa05d04..ac12e54 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -965,7 +965,7 @@ function image_style_path($style_name, $uri) { * @see image_effect_definition_load() */ function image_effect_definitions() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // hook_image_effect_info() includes translated strings, so each language is // cached separately. diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 46ba812..ee166c0 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -243,7 +243,7 @@ function language_delete($langcode) { * and checks to see if a related right to left CSS file should be included. */ function language_css_alter(&$css) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // If the current language is RTL, add the CSS file with the RTL overrides. if ($language_interface->direction == LANGUAGE_RTL) { diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index 01c39a8..78f958b 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -52,7 +52,7 @@ const LANGUAGE_NEGOTIATION_URL_DOMAIN = 1; * The current interface language code. */ function language_from_interface() { - return drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + return language_manager(LANGUAGE_TYPE_INTERFACE)->langcode; } /** @@ -200,7 +200,7 @@ function language_from_session($languages) { * @return * A valid language code on success, FALSE otherwise. */ -function language_from_url($languages) { +function language_from_url($languages, $args = array()) { $language_url = FALSE; if (!language_negotiation_method_enabled(LANGUAGE_NEGOTIATION_URL)) { @@ -212,8 +212,22 @@ function language_from_url($languages) { // Language negotiation happens before the public function current_path() // is available. // @todo Refactor with Symfony's Request object. - list($language, $path) = language_url_split_prefix(_current_path(), $languages); - _current_path($path); + if (isset($args['request'])) { + $request = $args['request']; + + $current_path = $request->attributes->get('system_path'); + if (!isset($current_path)) { + $current_path = trim($request->getPathInfo(), '/'); + } + } + else { + $current_path = _current_path(); + } + + list($language, $path) = language_url_split_prefix($current_path, $languages); + if ($request) { + $request->attributes->set('system_path', $path); + } if ($language !== FALSE) { $language_url = $language->langcode; } @@ -278,7 +292,7 @@ function language_from_url($languages) { * @return * A valid language code. */ -function language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_INTERFACE) { +function language_url_fallback($language = NULL, $args = array(), $language_type = LANGUAGE_TYPE_INTERFACE) { $default = language_default(); $prefix = (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX) == LANGUAGE_NEGOTIATION_URL_PREFIX); @@ -291,7 +305,8 @@ function language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_ return $default->langcode; } else { - return drupal_container()->get($language_type)->langcode; + $langcode = language_manager($language_type)->langcode; + return $langcode; } } @@ -321,7 +336,7 @@ function language_switcher_url($type, $path) { */ function language_switcher_session($type, $path) { $param = variable_get('language_negotiation_session_param', 'language'); - $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : drupal_container()->get($type)->langcode; + $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : language_manager($type)->langcode; $languages = language_list(); $links = array(); @@ -364,7 +379,7 @@ function language_url_rewrite_url(&$path, &$options) { // Language can be passed as an option, or we go for current URL language. if (!isset($options['language'])) { - $language_url = drupal_container()->get(LANGUAGE_TYPE_URL); + $language_url = language_manager(LANGUAGE_TYPE_URL); $options['language'] = $language_url; } // We allow only enabled languages here. diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php index fd4a865..bd940d3 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php @@ -26,9 +26,8 @@ class LanguageDependencyInjectionTest extends WebTestBase { function setUp() { parent::setUp('language'); - // Set up a new container to ensure we are building a new Language object - // for each test. - drupal_container(new ContainerBuilder()); + // Ensure we are building a new Language object for each test. + language_manager(); } @@ -42,7 +41,7 @@ class LanguageDependencyInjectionTest extends WebTestBase { drupal_language_initialize(); $expected = language_default(); - $result = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $result = language_manager(LANGUAGE_TYPE_INTERFACE); foreach ($expected as $property => $value) { $this->assertEqual($expected->$property, $result->$property, t('The dependency injected language object %prop property equals the new Language object %prop property.', array('%prop' => $property))); } @@ -61,6 +60,7 @@ class LanguageDependencyInjectionTest extends WebTestBase { 'name' => 'French', 'direction' => 0, 'weight' => 0, + 'method_id' => 'language-default', 'default' => TRUE, ); variable_set('language_default', $new_language_default); @@ -71,7 +71,7 @@ class LanguageDependencyInjectionTest extends WebTestBase { // The langauge system creates a Language object which contains the // same properties as the new default language object. $expected = new Language($new_language_default); - $result = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $result = language_manager(LANGUAGE_TYPE_INTERFACE); foreach ($expected as $property => $value) { $this->assertEqual($expected->$property, $result->$property, t('The dependency injected language object %prop property equals the default language object %prop property.', array('%prop' => $property))); } diff --git a/core/modules/language/tests/language_test.module b/core/modules/language/tests/language_test.module index 7829674..cc2e8ad 100644 --- a/core/modules/language/tests/language_test.module +++ b/core/modules/language/tests/language_test.module @@ -22,8 +22,8 @@ function language_test_boot() { */ function language_test_init() { language_test_store_language_negotiation(); - if (isset(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode) && isset(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->method_id)) { - drupal_set_message(t('Language negotiation method: @name', array('@name' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->method_id))); + if (isset(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode) && isset(language_manager(LANGUAGE_TYPE_INTERFACE)->method_id)) { + drupal_set_message(t('Language negotiation method: @name', array('@name' => language_manager(LANGUAGE_TYPE_INTERFACE)->method_id))); } } @@ -95,7 +95,7 @@ function language_test_language_negotiation_info_alter(array &$negotiation_info) function language_test_store_language_negotiation() { $last = array(); foreach (language_types_get_all() as $type) { - $last[$type] = drupal_container()->get($type)->langcode; + $last[$type] = language_manager($type)->langcode; } variable_set('language_test_language_negotiation_last', $last); } diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php index b63e8cd..c52f483 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php @@ -46,10 +46,12 @@ class LocaleUninstallTest extends WebTestBase { 'default' => $this->langcode == 'fr', ); language_save($language); - + // Reset the language_manager so that the language interface object gets + // freshly initialized. + language_manager(); // Check the UI language. drupal_language_initialize(); - $this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode))); + $this->assertEqual(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => language_manager(LANGUAGE_TYPE_INTERFACE)->langcode))); // Enable multilingual workflow option for articles. variable_set('node_type_language_hidden_article',FALSE); @@ -91,10 +93,12 @@ class LocaleUninstallTest extends WebTestBase { // Visit the front page. $this->drupalGet(''); - + // Reset the language_manager so that the language interface object gets + // freshly initialized. + language_manager(); // Check the init language logic. drupal_language_initialize(); - $this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, 'en', t('Language after uninstall: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode))); + $this->assertEqual(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode, 'en', t('Language after uninstall: %lang', array('%lang' => language_manager(LANGUAGE_TYPE_INTERFACE)->langcode))); // Check JavaScript files deletion. $this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found')))); diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index ce20b59..92b8c1e 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -232,7 +232,7 @@ function locale_language_delete($language) { * Language code to use for the lookup. */ function locale($string = NULL, $context = NULL, $langcode = NULL) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Use the advanced drupal_static() pattern, since this is called very often. static $drupal_static_fast; @@ -280,7 +280,7 @@ function locale_reset() { * plural formula. */ function locale_get_plural($count, $langcode = NULL) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Used to locally cache the plural formulas for all languages. $plural_formulas = &drupal_static(__FUNCTION__, array()); @@ -366,7 +366,7 @@ function locale_system_update($components) { * file if necessary, and adds it to the page. */ function locale_js_alter(&$javascript) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $dir = 'public://' . variable_get('locale_js_directory', 'languages'); $parsed = variable_get('javascript_parsed', array()); @@ -426,7 +426,7 @@ function locale_js_alter(&$javascript) { */ function locale_library_info_alter(&$libraries, $module) { if ($module == 'system' && isset($libraries['jquery.ui.datepicker'])) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // locale.datepicker.js should be added in the JS_LIBRARY group, so that // this attach behavior will execute early. JS_LIBRARY is the default for // hook_library_info_alter(), thus does not have to be specified explicitly. @@ -572,7 +572,7 @@ function locale_form_system_file_system_settings_alter(&$form, $form_state) { */ function locale_preprocess_node(&$variables) { if ($variables['langcode'] != LANGUAGE_NOT_SPECIFIED) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $node_language = language_load($variables['langcode']); if ($node_language->langcode != $language_interface->langcode) { @@ -771,7 +771,7 @@ function _locale_invalidate_js($langcode = NULL) { */ function _locale_rebuild_js($langcode = NULL) { if (!isset($langcode)) { - $language = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language = language_manager(LANGUAGE_TYPE_INTERFACE); } else { // Get information about the locale. diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index b91d3a4..25f45fc 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -103,7 +103,7 @@ function locale_translate_filters() { } // Pick the current interface language code for the filter. - $default_langcode = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + $default_langcode = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode; if (!isset($language_options[$default_langcode])) { $available_langcodes = array_keys($language_options); $default_langcode = array_shift($available_langcodes); diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php index 9d98550..3eeaf26 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php @@ -23,7 +23,7 @@ class NodeTokenReplaceTest extends NodeTestBase { * Creates a node, then tests the tokens generated from it. */ function testNodeTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $url_options = array( 'absolute' => TRUE, 'language' => $language_interface, diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 55e346e..2bee80e 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -646,7 +646,7 @@ function node_field_extra_fields() { function node_type_get_default_langcode($node_type) { $default_value = variable_get('node_type_language_default_' . $node_type, 'site_default'); - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); if ($default_value == LANGUAGE_NOT_SPECIFIED) { return LANGUAGE_NOT_SPECIFIED; @@ -736,7 +736,7 @@ function node_type_update_nodes($old_type, $type) { * type object by $type->disabled being set to TRUE. */ function _node_types_build($rebuild = FALSE) { - $cid = 'node_types:' . drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + $cid = 'node_types:' . language_manager(LANGUAGE_TYPE_INTERFACE)->langcode; if (!$rebuild) { $_node_types = &drupal_static(__FUNCTION__); @@ -1179,7 +1179,7 @@ function node_revision_delete($revision_id) { */ function node_view(Node $node, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Populate $node->content with a render() array. @@ -1240,7 +1240,7 @@ function node_view(Node $node, $view_mode = 'full', $langcode = NULL) { */ function node_build_content(Node $node, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Remove previously built content, if exists. @@ -2445,7 +2445,7 @@ function node_block_list_alter(&$blocks) { */ function node_feed($nids = FALSE, $channel = array()) { global $base_url; - $language_content = drupal_container()->get(LANGUAGE_TYPE_CONTENT); + $language_content = language_manager(LANGUAGE_TYPE_CONTENT); $rss_config = config('system.rss'); if ($nids === FALSE) { diff --git a/core/modules/openid/openid.inc b/core/modules/openid/openid.inc index d594dde..f6dc2a5 100644 --- a/core/modules/openid/openid.inc +++ b/core/modules/openid/openid.inc @@ -83,7 +83,7 @@ function openid_redirect_http($url, $message) { * Creates a js auto-submit redirect for (for the 2.x protocol) */ function openid_redirect($url, $message) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $output = '' . "\n"; $output .= '' . "\n"; diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index e57ff5f..c4fc134 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -333,7 +333,7 @@ function overlay_user_dismiss_message() { // @todo CSRF tokens are validated in page callbacks rather than access // callbacks, because access callbacks are also invoked during menu link // generation. Add token support to routing: http://drupal.org/node/755584. - $token = request()->query->get('token'); + $token = drupal_container()->get('request')->query->get('token'); if (!isset($token) || !drupal_valid_token($token, 'overlay')) { throw new AccessDeniedHttpException(); } @@ -693,7 +693,7 @@ function overlay_overlay_child_initialize() { // it to the same content rendered in overlay_exit(), at the end of the page // request. This allows us to check if anything actually did change, and, if // so, trigger an immediate Ajax refresh of the parent window. - $token = request()->query->get('token'); + $token = drupal_container()->get('request')->query->get('token'); if (!empty($_POST) || isset($token)) { foreach (overlay_supplemental_regions() as $region) { overlay_store_rendered_content($region, overlay_render_region($region)); diff --git a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php index e0d7e7c..5444d2b 100644 --- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php +++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php @@ -49,7 +49,9 @@ class PathAliasTest extends PathTestBase { // Visit the alias for the node and confirm a cache entry is created. cache('path')->flush(); $this->drupalGet($edit['alias']); - $this->assertTrue(cache('path')->get($edit['source']), t('Cache entry was created.')); + // @todo The alias should actually have been cached with the system path as + // the key, see the todo in drupal_cache_system_paths() in path.inc. + $this->assertTrue(cache('path')->get($edit['alias']), t('Cache entry was created.')); } /** diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php index 3aaab13..56e0854 100644 --- a/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php +++ b/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php @@ -23,7 +23,7 @@ class PollTokenReplaceTest extends PollTestBase { * Creates a poll, then tests the tokens generated from it. */ function testPollTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Craete a poll with three choices. $title = $this->randomName(); diff --git a/core/modules/search/search.pages.inc b/core/modules/search/search.pages.inc index c940223..9709737 100644 --- a/core/modules/search/search.pages.inc +++ b/core/modules/search/search.pages.inc @@ -104,7 +104,7 @@ function template_preprocess_search_results(&$variables) { * @see search-result.tpl.php */ function template_preprocess_search_result(&$variables) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $result = $variables['result']; $variables['url'] = check_url($result['link']); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 794054d..e5107e8 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -622,7 +622,7 @@ abstract class TestBase { */ protected function prepareEnvironment() { global $user, $conf; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Backup current in-memory configuration. $this->originalConf = $conf; @@ -690,7 +690,7 @@ abstract class TestBase { */ protected function tearDown() { global $user, $conf; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // In case a fatal error occurred that was not in the test process read the // log to pick up any fatal errors. diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 73afaa6..d282679 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -579,7 +579,7 @@ abstract class WebTestBase extends TestBase { */ protected function setUp() { global $user, $conf; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Create the database prefix for this test. $this->prepareDatabasePrefix(); diff --git a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php index 0cc6e41..fcfc21e 100644 --- a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php +++ b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php @@ -23,7 +23,7 @@ class StatisticsTokenReplaceTest extends StatisticsTestBase { * Creates a node, then tests the statistics tokens generated from it. */ function testStatisticsTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Create user and node. $user = $this->drupalCreateUser(array('create page content')); diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php index d18b273..8a13da3 100644 --- a/core/modules/system/language.api.php +++ b/core/modules/system/language.api.php @@ -26,7 +26,7 @@ function hook_language_init() { global $conf; - switch (drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode) { + switch (language_manager(LANGUAGE_TYPE_INTERFACE)->langcode) { case 'it': $conf['system.site']['name'] = 'Il mio sito Drupal'; break; @@ -52,7 +52,7 @@ function hook_language_init() { * The current path. */ function hook_language_switch_links_alter(array &$links, $type, $path) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); if ($type == LANGUAGE_TYPE_CONTENT && isset($links[$language_interface->langcode])) { foreach ($links[$language_interface->langcode] as $link) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php new file mode 100644 index 0000000..fef908c --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php @@ -0,0 +1,44 @@ + 'Bundle Registration', + 'description' => 'Tests bundle registration to the DIC.', + 'group' => 'Bundle', + ); + } + + function setUp() { + parent::setUp('bundle_test'); + } + + /** + * Test that services provided by module bundles get registered to the DIC. + */ + function testBundleRegistration() { + // The page callback at /bundle_test checks + // drupal_container()->has('bundle_test_class') + // and if this returns TRUE it outputs a message to this effect. We just + // need to check that the message appears on the page. + $this->drupalGet('bundle_test'); + $this->assertText(t('The service with id bundle_test_class is available in the DIC'), t('The bundle_test_class service has been registered to the DIC')); + // The event subscriber method in the test class calls drupal_set_message with + // a message saying it has fired. This will fire on every page request so it + // should show up on the front page. + $this->drupalGet(''); + $this->assertText(t('The bundle_test event subscriber fired!'), t('The bundle_test event subscriber fired')); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php index 397762b..8452c41 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php @@ -222,7 +222,7 @@ class CascadingStylesheetsTest extends WebTestBase { */ function testAlter() { // Switch the language to a right to left language and add system.base.css. - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $language_interface->direction = LANGUAGE_RTL; $path = drupal_get_path('module', 'system'); drupal_add_css($path . '/system.base.css'); diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php index 7a71d33..5bfb9b6 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php @@ -72,7 +72,7 @@ class FormatDateTest extends WebTestBase { function testFormatDate() { global $user; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $timestamp = strtotime('2007-03-26T00:00:00+00:00'); $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'America/Los_Angeles', 'en'), 'Sunday, 25-Mar-07 17:00:00 PDT', t('Test all parameters.')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php index d4eceba..ac1e611 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php @@ -41,7 +41,7 @@ class MailTest extends WebTestBase implements MailInterface { * Assert that the pluggable mail system is functional. */ public function testPluggableFramework() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Use MailTestCase for sending a message. $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface); diff --git a/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php b/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php index c329b96..9611f5e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php @@ -30,7 +30,7 @@ class TokenReplaceTest extends WebTestBase { $node = $this->drupalCreateNode(array('uid' => $account->uid)); $node->title = 'Blinking Text'; global $user; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $source = '[node:title]'; // Title of the node we passed in $source .= '[node:author:name]'; // Node author's name @@ -75,7 +75,7 @@ class TokenReplaceTest extends WebTestBase { * Test whether token-replacement works in various contexts. */ function testSystemTokenRecognition() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Generate prefixes and suffixes for the token context. $tests = array( @@ -104,7 +104,7 @@ class TokenReplaceTest extends WebTestBase { * Tests the generation of all system site information tokens. */ function testSystemSiteTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $url_options = array( 'absolute' => TRUE, 'language' => $language_interface, @@ -147,7 +147,7 @@ class TokenReplaceTest extends WebTestBase { * Tests the generation of all system date tokens. */ function testSystemDateTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Set time to one hour before request. $date = REQUEST_TIME - 3600; diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 3d2cae0..0dc087d 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -1896,7 +1896,7 @@ function hook_custom_theme() { */ function hook_watchdog(array $log_entry) { global $base_url; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $severity_list = array( WATCHDOG_EMERGENCY => t('Emergency'), diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 4c34dd2..88afd9c 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2067,7 +2067,7 @@ function system_filetransfer_info() { function system_init() { global $conf; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // For each date type (e.g. long, short), get the localized date format // for the user's current language and override the default setting for it // in $conf. This should happen on all pages except the date and time formats @@ -2200,7 +2200,8 @@ function system_add_module_assets() { * Implements hook_custom_theme(). */ function system_custom_theme() { - if ($request = request()) { + if (drupal_container()->has('request')) { + $request = drupal_container()->get('request'); $path = $request->attributes->get('system_path'); if (user_access('view the administration theme') && path_is_admin($path)) { return variable_get('admin_theme'); diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php index 9364685..91ad800 100644 --- a/core/modules/system/tests/http.php +++ b/core/modules/system/tests/http.php @@ -5,6 +5,7 @@ * Fake an HTTP request, for use during testing. */ +use Drupal\Core\DrupalKernel; use Symfony\Component\HttpFoundation\Request; // Set a global variable to indicate a mock HTTP request. @@ -32,10 +33,10 @@ if (!drupal_valid_test_ua()) { // Continue with normal request handling. $request = Request::createFromGlobals(); -request($request); drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); -$kernel = drupal_container()->get('httpkernel'); +$kernel = new DrupalKernel('prod', FALSE); +$kernel->boot(); $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response); diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index 11b7e13..f5f7ce7 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -5,6 +5,7 @@ * Fake an https request, for use during testing. */ +use Drupal\Core\DrupalKernel; use Symfony\Component\HttpFoundation\Request; // Set a global variable to indicate a mock HTTPS request. @@ -31,10 +32,10 @@ if (!drupal_valid_test_ua()) { // Continue with normal request handling. $request = Request::createFromGlobals(); -request($request); drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); -$kernel = drupal_container()->get('httpkernel'); +$kernel = new DrupalKernel('prod', FALSE); +$kernel->boot(); $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response); diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.info b/core/modules/system/tests/modules/bundle_test/bundle_test.info new file mode 100644 index 0000000..ec79843 --- /dev/null +++ b/core/modules/system/tests/modules/bundle_test/bundle_test.info @@ -0,0 +1,6 @@ +name = "Bundle test" +description = "Support module for bundle testing." +package = Testing +version = VERSION +core = 8.x +hidden = TRUE diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.module b/core/modules/system/tests/modules/bundle_test/bundle_test.module new file mode 100644 index 0000000..5f30b8f --- /dev/null +++ b/core/modules/system/tests/modules/bundle_test/bundle_test.module @@ -0,0 +1,26 @@ + MENU_CALLBACK, + 'title' => t('Bundle test callback'), + 'page callback' => 'bundle_test_callback', + 'access callback' => TRUE, + ); + return $items; +} + +/** + * Simple callback for testing that the bundle_test_class service exists in the + * DIC. + */ +function bundle_test_callback() { + if (drupal_container()->has('bundle_test_class')) { + return t('The service with id bundle_test_class is available in the DIC'); + } + return t('Service not found'); +} + diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php new file mode 100644 index 0000000..c124007 --- /dev/null +++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php @@ -0,0 +1,24 @@ +register('bundle_test_class', 'Drupal\bundle_test\TestClass') + ->addTag('kernel.event_subscriber'); + } +} diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php new file mode 100644 index 0000000..f58f9c9 --- /dev/null +++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php @@ -0,0 +1,33 @@ +get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); // Create two taxonomy terms. $term1 = $this->createTerm($this->vocabulary); diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 1086f19..6fdc6bf 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -585,7 +585,7 @@ function taxonomy_term_delete_multiple(array $tids) { */ function taxonomy_term_view(Term $term, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } field_attach_prepare_view('taxonomy_term', array($term->tid => $term), $view_mode, $langcode); diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php b/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php index 5cd3cd3..f257118 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php @@ -25,7 +25,7 @@ class UserTokenReplaceTest extends WebTestBase { * Creates a user, then tests the tokens generated from it. */ function testUserTokenReplacement() { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $url_options = array( 'absolute' => TRUE, 'language' => $language_interface, diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 2250110..ddc1147 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -709,7 +709,7 @@ function user_user_view($account) { */ function user_account_form(&$form, &$form_state) { global $user; - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $account = $form['#user']; $register = ($form['#user']->uid > 0 ? FALSE : TRUE); @@ -2368,7 +2368,7 @@ function user_view_page($account) { */ function user_view($account, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Retrieve all profile fields and attach to $account->content. @@ -2404,7 +2404,7 @@ function user_view($account, $view_mode = 'full', $langcode = NULL) { */ function user_build_content($account, $view_mode = 'full', $langcode = NULL) { if (!isset($langcode)) { - $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode; + $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode; } // Remove previously built content, if exists. diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index b568f66..783e3ff 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -77,7 +77,7 @@ function user_pass_validate($form, &$form_state) { } function user_pass_submit($form, &$form_state) { - $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE); + $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE); $account = $form_state['values']['account']; // Mail one time login URL and instructions using current language. @@ -498,9 +498,9 @@ function user_page() { global $user; if ($user->uid) { // @todo: Cleaner sub request handling. - $subrequest = Request::create('/user/' . $user->uid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all()); - request($subrequest); - return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); + $request = drupal_container()->get('request'); + $subrequest = Request::create('/user/' . $user->uid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all()); + return drupal_container()->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); } else { return drupal_get_form('user_login'); diff --git a/core/update.php b/core/update.php index 85c45c0..b685332 100644 --- a/core/update.php +++ b/core/update.php @@ -383,18 +383,10 @@ update_prepare_d8_bootstrap(); // Determine if the current user has access to run update.php. drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION); - -// Ensure the default language is properly registered within the Dependency -// Injection container during the upgrade process. -$default = language_default(); -drupal_container()->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language') - ->addMethodCall('extend', array($default)); - // A request object from the HTTPFoundation to tell us about the request. // @todo These two lines were copied from index.php which has its own todo about // a change required here. Revisit this when that change has been made. $request = Request::createFromGlobals(); -request($request); // There can be conflicting 'op' parameters because both update and batch use // this parameter name. We need the 'op' coming from a POST request to trump diff --git a/index.php b/index.php index 7b99d10..38177ab 100644 --- a/index.php +++ b/index.php @@ -11,31 +11,27 @@ * See COPYRIGHT.txt and LICENSE.txt files in the "core" directory. */ +use Drupal\Core\DrupalKernel; use Symfony\Component\HttpFoundation\Request; /** * Root directory of Drupal installation. */ define('DRUPAL_ROOT', getcwd()); -// Bootstrap the lowest level of what we need. -require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc'; -drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); - -// Create a request object from the HTTPFoundation. -$request = Request::createFromGlobals(); - -// Set the global $request object. This is a temporary measure to keep legacy -// utility functions working. It should be moved to a dependency injection -// container at some point. -request($request); // Bootstrap all of Drupal's subsystems, but do not initialize anything that // depends on the fully resolved Drupal path, because path resolution happens // during the REQUEST event of the kernel. // @see Drupal\Core\EventSubscriber\PathSubscriber; // @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; +require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); -$kernel = drupal_container()->get('httpkernel'); +// @todo Figure out how best to handle the Kernel constructor parameters. +$kernel = new DrupalKernel('prod', FALSE); + +// Create a request object from the HTTPFoundation. +$request = Request::createFromGlobals(); $response = $kernel->handle($request)->prepare($request)->send(); + $kernel->terminate($request, $response);