summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2013-11-19 16:21:35 (GMT)
committerNathaniel Catchpole2013-11-19 16:21:35 (GMT)
commit92f93a1cbc2b331e4427efe8ca7674fb503c33a3 (patch)
tree662d7365925889652ab3807c3e2601a58fcd5bf7
parentfc04601c357609f6cae7cb3ae6c71610d44647e5 (diff)
Issue #2004086 by dawehner, pwolanin, katbailey, tim.plunkett, vijaycs85, fabpot: The Request service must be synthetic.
-rw-r--r--core/core.services.yml12
-rw-r--r--core/includes/bootstrap.inc20
-rw-r--r--core/includes/install.inc13
-rw-r--r--core/lib/Drupal/Core/Ajax/AjaxResponse.php25
-rw-r--r--core/lib/Drupal/Core/DrupalKernel.php19
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php40
-rw-r--r--core/modules/comment/lib/Drupal/comment/Entity/Comment.php4
-rw-r--r--core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php4
-rw-r--r--core/modules/simpletest/lib/Drupal/simpletest/TestBase.php9
-rw-r--r--core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php12
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php5
-rwxr-xr-xcore/scripts/run-tests.sh9
-rw-r--r--core/update.php5
13 files changed, 143 insertions, 34 deletions
diff --git a/core/core.services.yml b/core/core.services.yml
index 4e28f55..f371585 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -211,17 +211,12 @@ 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
plugin.manager.menu.contextual_link:
class: Drupal\Core\Menu\ContextualLinkManager
arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
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']
@@ -365,6 +360,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:
@@ -436,7 +435,6 @@ services:
- [setCurrentUser, ['@?current_user']]
tags:
- { name: event_subscriber }
- scope: request
access_route_subscriber:
class: Drupal\Core\EventSubscriber\AccessRouteSubscriber
tags:
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 109ff24..f414d53 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1552,7 +1552,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.
}
@@ -1718,9 +1718,18 @@ 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);
@@ -1861,10 +1870,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);
@@ -1994,6 +2006,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..f6848c9 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..6619a56 100644
--- a/core/lib/Drupal/Core/Ajax/AjaxResponse.php
+++ b/core/lib/Drupal/Core/Ajax/AjaxResponse.php
@@ -9,6 +9,7 @@ namespace Drupal\Core\Ajax;
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 @@ class AjaxResponse extends JsonResponse {
}
/**
- * 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 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 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
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 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
// 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..cf4dca1
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\EventSubscriber\AjaxResponseSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Drupal\Core\Ajax\AjaxResponse;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+class AjaxResponseSubscriber implements EventSubscriberInterface {
+
+ /**
+ * Renders the ajax commands right before preparing the result.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+ * The response event, which contains the possible AjaxResponse object.
+ */
+ public function onResponse(FilterResponseEvent $event) {
+ $response = $event->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 4d22fbf..209d08b 100644
--- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
+++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
@@ -216,10 +216,10 @@ class Comment extends ContentEntityBase implements CommentInterface {
public function preSave(EntityStorageControllerInterface $storage_controller) {
parent::preSave($storage_controller);
- global $user;
+ $user = \Drupal::currentUser();
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;
}
if ($this->isNew()) {
// Add the comment to database. This next section builds the thread field.
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 Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
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 @@ abstract class DrupalUnitTestBase extends UnitTestBase {
$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 c00f72f..2108b67 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\Config\StorageInterface;
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 @@ abstract class TestBase {
// Register info parser.
$this->container->register('info_parser', 'Drupal\Core\Extension\InfoParser');
+ $request = Request::create('/');
+ $this->container->set('request', $request);
+ $this->container->set('current_user', $GLOBALS['user']);
+
\Drupal::setContainer($this->container);
// Unset globals.
@@ -1035,12 +1040,16 @@ abstract class TestBase {
* 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->set('request', $request);
$this->container->set('current_user', $GLOBALS['user']);
}
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 7af12f7..0268284 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
@@ -14,6 +14,7 @@ use Drupal\views\Plugin\views\area\AreaPluginBase;
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
@@ -886,8 +887,15 @@ abstract class DisplayPluginBase extends PluginBase {
// 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 dc51709..b4e343d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php
@@ -81,11 +81,14 @@ class DisplayPageTest extends ViewUnitTestBase {
$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 58f45ae..7912f6a 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -39,6 +39,10 @@ if (!\Drupal::moduleHandler()->moduleExists('simpletest')) {
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 7abd566..f3f381b 100644
--- a/core/update.php
+++ b/core/update.php
@@ -450,13 +450,14 @@ update_prepare_d8_bootstrap();
// 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();