diff --git a/core/core.services.yml b/core/core.services.yml index 12f3a3c..b73e700 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -196,14 +196,9 @@ services: plugin.manager.menu.local_task: class: Drupal\Core\Menu\LocalTaskManager arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user'] - scope: request request: class: Symfony\Component\HttpFoundation\Request - # @TODO the synthetic setting must be uncommented whenever drupal_session_initialize() - # is run after there is a request and the following two lines should be removed. - factory_class: Symfony\Component\HttpFoundation\Request - factory_method: createFromGlobals - #synthetic: true + synthetic: true event_dispatcher: class: Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher arguments: ['@service_container'] @@ -347,6 +342,10 @@ services: tags: - { name: event_subscriber } arguments: ['@settings'] + ajax_response_subscriber: + class: Drupal\Core\EventSubscriber\AjaxResponseSubscriber + tags: + - { name: event_subscriber } route_enhancer.authentication: class: Drupal\Core\Routing\Enhancer\AuthenticationEnhancer calls: diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 399c9fb..8f931c6 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -1549,7 +1549,7 @@ function watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG $log_entry['referer'] = $request->headers->get('Referer', ''); $log_entry['ip'] = $request->getClientIP(); } - catch (\InvalidArgumentException $e) { + catch (DependencyInjectionRuntimeException $e) { // We are not in a request context. } @@ -1715,9 +1715,17 @@ function drupal_set_title($title = NULL, $output = Title::CHECK_PLAIN) { * The user session object. */ function drupal_anonymous_user() { + try { + $request = Drupal::request(); + $hostname = $request->getClientIP(); + } catch (DependencyInjectionRuntimeException $e) { + // We are not in a request context. + $hostname = ''; + } + $values = array( 'uid' => 0, - 'hostname' => \Drupal::request()->getClientIP(), + 'hostname' => $hostname, 'roles' => array(DRUPAL_ANONYMOUS_RID), ); return new UserSession($values); @@ -1858,10 +1866,13 @@ function drupal_handle_request($test_only = FALSE) { // @todo Remove this once everything in the bootstrap has been // converted to services in the DIC. $kernel->boot(); - drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); // Create a request object from the HttpFoundation. $request = Request::createFromGlobals(); + Drupal::getContainer()->set('request', $request); + + drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); + $response = $kernel->handle($request)->prepare($request)->send(); $kernel->terminate($request, $response); @@ -1991,6 +2002,8 @@ function _drupal_bootstrap_kernel() { if (!\Drupal::getContainer()) { $kernel = new DrupalKernel('prod', drupal_classloader()); $kernel->boot(); + $request = Request::createFromGlobals(); + Drupal::getContainer()->set('request', $request); } } diff --git a/core/includes/install.inc b/core/includes/install.inc index 4e70be4..9e53f18 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -625,10 +625,19 @@ function drupal_install_system() { // Create tables. drupal_install_schema('system'); - if (!drupal_container()->has('kernel')) { - // Immediately boot a kernel to have real services ready. + if (!Drupal::getContainer()->has('kernel')) { + // Immediately boot a kernel to have real services ready. If there's already + // an initialized request object in the pre-kernel container, persist it in + // the post-kernel container. + if (Drupal::getContainer()->initialized('request')) { + $request = Drupal::request(); + } $kernel = new DrupalKernel('install', drupal_classloader(), FALSE); $kernel->boot(); + if (isset($request)) { + Drupal::getContainer()->set('request', $request); + } + } $system_path = drupal_get_path('module', 'system'); diff --git a/core/lib/Drupal/Core/Ajax/AjaxResponse.php b/core/lib/Drupal/Core/Ajax/AjaxResponse.php index 44d146a..a460f19 100644 --- a/core/lib/Drupal/Core/Ajax/AjaxResponse.php +++ b/core/lib/Drupal/Core/Ajax/AjaxResponse.php @@ -9,6 +9,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; /** * JSON response object for AJAX requests. @@ -46,17 +47,25 @@ public function addCommand($command, $prepend = FALSE) { } /** - * Sets the response's data to be the array of AJAX commands. - * - * @param Request $request - * A request object. + * {@inheritdoc} * - * @return Response - * The current response. + * Sets the response's data to be the array of AJAX commands. */ public function prepare(Request $request) { - $this->setData($this->ajaxRender($request)); - return parent::prepare($request); + $this->prepareResponse($request); + return $this; + } + + /** + * Sets the rendered ajax ajax right before the response is prepared + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object. + */ + public function prepareResponse(Request $request) { + if ($this->data == '{}') { + $this->setData($this->ajaxRender($request)); + } } /** diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 3e97607..8d6e28c 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -369,10 +369,17 @@ protected function getKernelParameters() { protected function initializeContainer() { $this->containerNeedsDumping = FALSE; $persist = $this->getServicesToPersist(); - // If we are rebuilding the kernel and we are in a request scope, store - // request info so we can add them back after the rebuild. - if (isset($this->container) && $this->container->hasScope('request')) { - $request = $this->container->get('request'); + // The request service requires custom persisting logic, since it is also + // potentially scoped. During Drupal installation, there is a request + // service without a request scope. + $request_scope = FALSE; + if (isset($this->container)) { + if ($this->container->isScopeActive('request')) { + $request_scope = TRUE; + } + if ($this->container->initialized('request')) { + $request = $this->container->get('request'); + } } $this->container = NULL; $class = $this->getClassName(); @@ -445,8 +452,10 @@ protected function initializeContainer() { // Set the class loader which was registered as a synthetic service. $this->container->set('class_loader', $this->classLoader); // If we have a request set it back to the new container. - if (isset($request)) { + if ($request_scope) { $this->container->enterScope('request'); + } + if (isset($request)) { $this->container->set('request', $request); } \Drupal::setContainer($this->container); diff --git a/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php new file mode 100644 index 0000000..967f79e --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php @@ -0,0 +1,39 @@ +getResponse(); + if ($response instanceof AjaxResponse) { + $response->prepareResponse($event->getRequest()); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[KernelEvents::RESPONSE][] = array('onResponse', -100); + + return $events; + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php index 35db484..9b7184c 100644 --- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php @@ -217,10 +217,13 @@ public function id() { public function preSave(EntityStorageControllerInterface $storage_controller) { parent::preSave($storage_controller); - global $user; + $user = \Drupal::currentUser(); + debug($this->status->value); + debug($user->id()); if (!isset($this->status->value)) { - $this->status->value = user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED; + $this->status->value = $user->hasPermission('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED; + debug($this->status->value); } if ($this->isNew()) { // Add the comment to database. This next section builds the thread field. diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php index 7944fdd..e1da4b9 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php @@ -155,7 +155,7 @@ protected function assertPublishedStatus() { * Tests translate link on comment content admin page. */ function testTranslateLinkCommentAdminPage() { - $this->admin_user = $this->drupalCreateUser(array_merge(parent::getTranslatorPermissions(), array('access administration pages', 'administer comments'))); + $this->admin_user = $this->drupalCreateUser(array_merge(parent::getTranslatorPermissions(), array('access administration pages', 'administer comments', 'skip comment approval'))); $this->drupalLogin($this->admin_user); $cid_translatable = $this->createEntity(array(), $this->langcodes[0]); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php index 269d2c5..83e34aa 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php @@ -36,7 +36,7 @@ function setUp() { // Add two users, create a node with the user1 as author and another node // with user2 as author. For the second node add a comment from user1. - $this->account = $this->drupalCreateUser(); + $this->account = $this->drupalCreateUser(array('skip comment approval')); $this->account2 = $this->drupalCreateUser(); $this->drupalLogin($this->account); diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php b/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php index dbf57b4..43fbe8a 100644 --- a/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php +++ b/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php @@ -172,6 +172,7 @@ public function testUserWithPermission() { $post = array('editors[0]' => 'form') + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('edit/attachments', 'application/vnd.drupal-ajax', $post); $ajax_commands = drupal_json_decode($response); + debug($ajax_commands); $this->assertIdentical(2, count($ajax_commands), 'The attachments HTTP request results in two AJAX commands.'); // First command: settings. $this->assertIdentical('settings', $ajax_commands[0]['command'], 'The first AJAX command is a settings command.'); diff --git a/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php b/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php index 6be87d0..a8fd7d4 100644 --- a/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php +++ b/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php @@ -196,6 +196,7 @@ function testGetUntransformedTextCommand() { 'data' => 'Test', ) ); + debug(json_decode($response->prepare($request)->getContent())); $this->assertEqual(drupal_json_encode($expected), $response->prepare($request)->getContent(), 'The GetUntransformedTextCommand AJAX command works correctly.'); } } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php index b7fb02f..5eb5b26 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\Reference; use Drupal\Core\Database\Database; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; /** * Base test case class for Drupal unit tests. @@ -188,7 +189,8 @@ public function containerBuild(ContainerBuilder $container) { $definition = $container->getDefinition('path_processor_alias'); $definition->clearTag('path_processor_inbound')->clearTag('path_processor_outbound'); } - + $request = Request::create('/'); + $this->container->set('request', $request); } /** diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index d0edfec..627800f 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -18,6 +18,7 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Language\Language; use Drupal\Core\StreamWrapper\PublicStream; +use Symfony\Component\HttpFoundation\Request; /** * Base class for Drupal tests. @@ -973,6 +974,10 @@ protected function prepareEnvironment() { // Register info parser. $this->container->register('info_parser', 'Drupal\Core\Extension\InfoParser'); + $request = Request::create('/'); + $request->attributes->set('_account', $GLOBALS['user']); + $this->container->set('request', $request); + \Drupal::setContainer($this->container); // Unset globals. @@ -1035,13 +1040,16 @@ protected function prepareConfigDirectories() { * enabled modules to be immediately available in the same request. */ protected function rebuildContainer() { + // Preserve the request object after the container rebuild. + $request = \Drupal::request(); + $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); $this->kernel->boot(); // DrupalKernel replaces the container in \Drupal::getContainer() with a // different object, so we need to replace the instance on this test class. $this->container = \Drupal::getContainer(); - // The global $user is set in TestBase::prepareEnvironment(). - $this->container->get('request')->attributes->set('_account', $GLOBALS['user']); + + $this->container->set('request', $request); } /** diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 8b528d3..cac3bb9 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -452,7 +452,7 @@ function user_access($string, AccountInterface $account = NULL) { if (!isset($account)) { // In the installer request session is not set, so we have to fall back // to the global $user. In all other cases the session key is preferred. - $account = \Drupal::request()->attributes->get('_account') ?: $user; + $account = \Drupal::currentUser() ?: $user; } return $account->hasPermission($string); diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index f37f950..660b7d8 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -12,6 +12,7 @@ use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\PluginBase; use Drupal\views\Views; +use Symfony\Component\DependencyInjection\Exception\RuntimeException as DependencyInjectionRuntimeException; /** * @defgroup views_display_plugins Views display plugins @@ -884,8 +885,15 @@ public function getHandlers($type) { // If this is during form submission and there are temporary options // which can only appear if the view is in the edit cache, use those // options instead. This is used for AJAX multi-step stuff. - if (\Drupal::request()->request->get('form_id') && isset($this->view->temporary_options[$type][$id])) { - $info = $this->view->temporary_options[$type][$id]; + // @todo Remove dependency on Request object + // https://drupal.org/node/2059003 + try { + $request = \Drupal::request(); + if ($request->request->get('form_id') && isset($this->view->temporary_options[$type][$id])) { + $info = $this->view->temporary_options[$type][$id]; + } + } + catch (DependencyInjectionRuntimeException $e) { } if ($info['id'] != $id) { diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php index 3e5b590..48c116e 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php @@ -80,11 +80,14 @@ public function testPageResponses() { $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); $this->assertEqual($response->getStatusCode(), 200); + $subrequest = Request::create('/test_page_display_200', 'GET'); + \Drupal::getContainer()->set('request', $subrequest); + // Test accessing a disabled page for a view. $view = views_get_view('test_page_display'); // Disable the view, rebuild menu, and request the page again. $view->storage->disable()->save(); - $subrequest = Request::create('/test_page_display_200', 'GET'); + $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); $this->assertEqual($response->getStatusCode(), 404); } diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index ae489e1..a9206e7 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -39,6 +39,10 @@ exit; } simpletest_classloader_register(); +// We have to add a Request. +$request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); +$container = Drupal::getContainer(); +$container->set('request', $request); if ($args['clean']) { // Clean up left-over times and directories. @@ -477,8 +481,11 @@ function simpletest_script_run_one_test($test_id, $test_class) { try { // Bootstrap Drupal. drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); - simpletest_classloader_register(); + // We have to add a Request. + $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); + $container = Drupal::getContainer(); + $container->set('request', $request); // Override configuration according to command line parameters. $conf['simpletest.settings']['verbose'] = $args['verbose']; diff --git a/core/update.php b/core/update.php index a77b5cd..23df2df 100644 --- a/core/update.php +++ b/core/update.php @@ -449,13 +449,14 @@ function update_check_requirements($skip_warnings = FALSE) { // Determine if the current user has access to run update.php. drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES); -require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc'); -drupal_session_initialize(); // A request object from the HTTPFoundation to tell us about the request. $request = Request::createFromGlobals(); \Drupal::getContainer()->set('request', $request); +require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc'); +drupal_session_initialize(); + // Ensure that URLs generated for the home and admin pages don't have 'update.php' // in them. $generator = \Drupal::urlGenerator();