diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/BundleConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/BundleConstraintValidator.php
index 0d46460..8a0ab7d 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/BundleConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/BundleConstraintValidator.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity\Plugin\Validation\Constraint;
 
+use Drupal\Core\Plugin\Plugin\DataType\DataTypeWrapper;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
@@ -23,6 +24,17 @@ public function validate($entity, Constraint $constraint) {
       return;
     }
 
+    // Validate against wrapper bundle constraint when necessary.
+    if ($entity instanceof DataTypeWrapper) {
+      $bundles = $entity->getDataDefinition()->getConstraint('Bundle');
+      $bundle = $bundles ? array_shift($bundles) : 0;
+      if ($bundle && !in_array($bundle, $constraint->getBundleOption())) {
+        $this->context->addViolation($constraint->message, array('%bundle' => implode(', ', $constraint->getBundleOption())));
+      }
+      // $entity is not an entity, so we should not continue.
+      return;
+    }
+
     if (!in_array($entity->bundle(), $constraint->getBundleOption())) {
       $this->context->addViolation($constraint->message, array('%bundle' => implode(', ', $constraint->getBundleOption())));
     }
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
index 1d26d0b..edfdeed 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityChangedConstraintValidator.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity\Plugin\Validation\Constraint;
 
+use Drupal\Core\Entity\EntityInterface;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
@@ -19,8 +20,8 @@ class EntityChangedConstraintValidator extends ConstraintValidator {
    * {@inheritdoc}
    */
   public function validate($entity, Constraint $constraint) {
-    if (isset($entity)) {
-      /** @var \Drupal\Core\Entity\EntityInterface $entity */
+    // Non-entities can be passed and should not be validated.
+    if (isset($entity) && $entity instanceof EntityInterface) {
       if (!$entity->isNew()) {
         $saved_entity = \Drupal::entityManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
         // A change to any other translation must add a violation to the current
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityTypeConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityTypeConstraintValidator.php
index b0a81d2..4816294 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityTypeConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityTypeConstraintValidator.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity\Plugin\Validation\Constraint;
 
+use Drupal\Core\Plugin\Plugin\DataType\DataTypeWrapper;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
@@ -23,6 +24,15 @@ public function validate($entity, Constraint $constraint) {
       return;
     }
 
+    // Validate against wrapper EntityType constraint when necessary.
+    if ($entity instanceof DataTypeWrapper) {
+      if ($entity->getDataDefinition()->getConstraint('EntityType') != $constraint->type) {
+        $this->context->addViolation($constraint->message, array('%type' => $constraint->type));
+        // $entity is not an entity, so we should not continue.
+        return;
+      }
+    }
+
     /** @var $entity \Drupal\Core\Entity\EntityInterface */
     if ($entity->getEntityTypeId() != $constraint->type) {
       $this->context->addViolation($constraint->message, array('%type' => $constraint->type));
diff --git a/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php b/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
index 8c31371..0e1ef99 100644
--- a/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
+++ b/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
@@ -9,7 +9,9 @@
 
 use Drupal\Component\Plugin\Exception\ContextException;
 use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\TypedData\TypedDataManagerInterface;
 
 /**
  * Provides methods to handle sets of contexts.
@@ -17,6 +19,22 @@
 class ContextHandler implements ContextHandlerInterface {
 
   /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManagerInterface
+   */
+  protected $typedDataManager;
+
+  /**
+   * ContextHandler constructor.
+   *
+   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
+   */
+  public function __construct(TypedDataManagerInterface $typed_data_manager) {
+    $this->typedDataManager = $typed_data_manager;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function filterPluginDefinitionsByContexts(array $contexts, array $definitions) {
@@ -56,11 +74,26 @@ public function getMatchingContexts(array $contexts, ContextDefinitionInterface
         return FALSE;
       }
 
-      // If any constraint does not match, this context is invalid.
-      foreach ($definition->getConstraints() as $constraint_name => $constraint) {
-        if ($context_definition->getConstraint($constraint_name) != $constraint) {
-          return FALSE;
+      // If the definition has constraints, validate the contexts against them.
+      if ($definition->getConstraints()) {
+        $constraints = [];
+        foreach ($definition->getConstraints() as $constraint_name => $constraint_settings) {
+          $constraints[] = $this->typedDataManager->getValidationConstraintManager()->create($constraint_name, $constraint_settings);
+        }
+        if ($context->hasContextValue()) {
+          $typed_data_definition = $context->getContextData();
+        }
+        else {
+          $typed_data_data_definition = $this->typedDataManager->createDataDefinition('data_type_wrapper');
+          foreach ($context_definition->getDataDefinition()->getConstraints() as $constraint => $constraint_settings) {
+            $typed_data_data_definition->addConstraint($constraint, $constraint_settings);
+          }
+          $typed_data_definition = $this->typedDataManager->create($typed_data_data_definition);
         }
+        $validator = $this->typedDataManager->getValidator();
+        $violations = $validator->validate($typed_data_definition, $constraints);
+        // Contexts without any violations are valid.
+        return !$violations->count();
       }
 
       // All contexts with matching data type and contexts are valid.
diff --git a/core/lib/Drupal/Core/Plugin/Plugin/DataType/DataTypeWrapper.php b/core/lib/Drupal/Core/Plugin/Plugin/DataType/DataTypeWrapper.php
new file mode 100644
index 0000000..171bed6
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Plugin/DataType/DataTypeWrapper.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Core\Plugin\Plugin\DataType\DataTypeWrapper.
+ */
+
+namespace Drupal\Core\Plugin\Plugin\DataType;
+
+
+use Drupal\Core\TypedData\TypedData;
+
+/**
+ * Defines a generic "wrapper" data type.
+ *
+ * Instances of this class are used to validate constraints against each other
+ * when a raw data object is not available to validate against.
+ *
+ * The plugin system ContextHandler class manually builds instances of this
+ * data type when a value is not passed with a context, but a context is
+ * available. This allows the ContextHandler to determine what contexts will be
+ * valid during run time based upon the available administrative information.
+ *
+ * @see \Drupal\Core\Plugin\Context\ContextHandler
+ *
+ * @DataType(
+ *   id = "data_type_wrapper",
+ *   label = @Translation("Wrapper for validating sets of constraints against settings instead of objects."),
+ *   unwrap_for_canonical_representation = FALSE
+ * )
+ */
+class DataTypeWrapper extends TypedData {}
diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist
index 2620fe9..3d87085 100644
--- a/core/phpunit.xml.dist
+++ b/core/phpunit.xml.dist
@@ -13,7 +13,7 @@
     <ini name="memory_limit" value="-1"/>
     <env name="SIMPLETEST_BASE_URL" value=""/>
     <!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
-    <env name="SIMPLETEST_DB" value=""/>
+    <env name="SIMPLETEST_DB" value="mysql://drupaluser:@127.0.0.1:33067/drupal_8_1_x"/>
     <!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/databasename#table_prefix -->
   </php>
   <testsuites>
diff --git a/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php b/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
index 981f4c2..c23564f 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
@@ -8,18 +8,20 @@
 namespace Drupal\Tests\Core\Plugin;
 
 use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\Context\ContextHandler;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\Plugin\DataType\StringData;
-use Drupal\Tests\UnitTestCase;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\simpletest\ContentTypeCreationTrait;
 
 /**
  * @coversDefaultClass \Drupal\Core\Plugin\Context\ContextHandler
  * @group Plugin
  */
-class ContextHandlerTest extends UnitTestCase {
+class ContextHandlerTest extends KernelTestBase {
+  use ContentTypeCreationTrait;
 
   /**
    * The context handler.
@@ -29,12 +31,25 @@ class ContextHandlerTest extends UnitTestCase {
   protected $contextHandler;
 
   /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['user', 'system', 'node', 'field', 'text', 'filter'];
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
-    $this->contextHandler = new ContextHandler();
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('node_type');
+    $this->installEntitySchema('node');
+    $this->installConfig('node');
+    $this->createContentType(['type' => 'page', 'name' => 'Page']);
+    $this->createContentType(['type' => 'article', 'name' => 'Article']);
+    $this->contextHandler = $this->container->get('context.handler');
   }
 
   /**
@@ -56,29 +71,21 @@ public function providerTestCheckRequirements() {
     $requirement_any = new ContextDefinition();
     $requirement_any->setRequired(TRUE);
 
-    $context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_any->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('empty')));
-
-    $requirement_specific = new ContextDefinition('specific');
-    $requirement_specific->setConstraints(array('bar' => 'baz'));
-
-    $context_constraint_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_constraint_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('foo')));
-    $context_datatype_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_datatype_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('fuzzy')));
-
-    $context_definition_specific = new ContextDefinition('specific');
-    $context_definition_specific->setConstraints(array('bar' => 'baz'));
-    $context_specific = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_specific->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue($context_definition_specific));
+    $context_any = new Context(new ContextDefinition('any'));
+
+    $requirement_specific = new ContextDefinition('entity:node');
+    $requirement_specific->setConstraints(array('Bundle' => [0 => 'page']));
+
+    $mismatch_def = new ContextDefinition('entity:node');
+    $context_constraint_mismatch = new Context($mismatch_def->setConstraints(array('Bundle' => [0 => 'article'])));
+
+    $context_datatype_mismatch = new Context(new ContextDefinition('entity:user'));
+
+    $specific_def = new ContextDefinition('entity:node');
+    $context_specific = new Context($specific_def->setConstraints(array('Bundle' => [0 => 'page'])));
+
+    $requirement_complex = new ContextDefinition('entity:node');
+    $requirement_complex->setConstraints(['Bundle' => [0 => 'page', 1 => 'article']]);
 
     $data = array();
     $data[] = array(array(), array(), TRUE);
@@ -89,7 +96,8 @@ public function providerTestCheckRequirements() {
     $data[] = array(array($context_constraint_mismatch), array($requirement_specific), FALSE);
     $data[] = array(array($context_datatype_mismatch), array($requirement_specific), FALSE);
     $data[] = array(array($context_specific), array($requirement_specific), TRUE);
-
+    $data[] = array(array($context_specific), array($requirement_complex), TRUE);
+    $data[] = array(array($context_constraint_mismatch), array($requirement_complex), TRUE);
     return $data;
   }
 
@@ -102,7 +110,7 @@ public function testGetMatchingContexts($contexts, $requirement, $expected = NUL
     if (is_null($expected)) {
       $expected = $contexts;
     }
-    $this->assertSame($expected, $this->contextHandler->getMatchingContexts($contexts, $requirement));
+    $this->assertEquals($expected, $this->contextHandler->getMatchingContexts($contexts, $requirement));
   }
 
   /**
@@ -111,29 +119,23 @@ public function testGetMatchingContexts($contexts, $requirement, $expected = NUL
   public function providerTestGetMatchingContexts() {
     $requirement_any = new ContextDefinition();
 
-    $requirement_specific = new ContextDefinition('specific');
-    $requirement_specific->setConstraints(array('bar' => 'baz'));
-
-    $context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_any->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('empty')));
-    $context_constraint_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_constraint_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('foo')));
-    $context_datatype_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_datatype_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('fuzzy')));
-    $context_definition_specific = new ContextDefinition('specific');
-    $context_definition_specific->setConstraints(array('bar' => 'baz'));
-    $context_specific = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_specific->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue($context_definition_specific));
+    $requirement_specific = new ContextDefinition('entity:node');
+    $requirement_specific->setConstraints(array('Bundle' => [0 => 'page']));
 
-    $data = array();
+    $context_any = new Context(new ContextDefinition());
+
+    $definition_constraint_mismatch = new ContextDefinition('entity:node');
+    $definition_constraint_mismatch->setConstraints(array('Bundle' => [0 => 'article']));
+    $context_constraint_mismatch = new Context($definition_constraint_mismatch);
+
+    $definition_datatype_mismatch = new ContextDefinition('entity:user');
+    $context_datatype_mismatch = new Context($definition_datatype_mismatch);
+
+    $context_definition_specific = new ContextDefinition('entity:node');
+    $context_definition_specific->setConstraints(array('Bundle' => [0 => 'page']));
+    $context_specific = new Context($context_definition_specific);
+
+    $data = [];
     // No context will return no valid contexts.
     $data[] = array(array(), $requirement_any);
     // A context with a generic matching requirement is valid.
@@ -145,7 +147,6 @@ public function providerTestGetMatchingContexts() {
     $data[] = array(array($context_constraint_mismatch), $requirement_specific, array());
     // A context with a mismatched datatype is invalid.
     $data[] = array(array($context_datatype_mismatch), $requirement_specific, array());
-
     return $data;
   }
 
@@ -154,19 +155,7 @@ public function providerTestGetMatchingContexts() {
    *
    * @dataProvider providerTestFilterPluginDefinitionsByContexts
    */
-  public function testFilterPluginDefinitionsByContexts($has_context, $definitions, $expected) {
-    if ($has_context) {
-      $context = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-      $expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(array('expected_constraint_name' => 'expected_constraint_value'));
-      $context->expects($this->atLeastOnce())
-        ->method('getContextDefinition')
-        ->will($this->returnValue($expected_context_definition));
-      $contexts = array($context);
-    }
-    else {
-      $contexts = array();
-    }
-
+  public function testFilterPluginDefinitionsByContexts($contexts, $definitions, $expected) {
     $this->assertSame($expected, $this->contextHandler->filterPluginDefinitionsByContexts($contexts, $definitions));
   }
 
@@ -174,56 +163,63 @@ public function testFilterPluginDefinitionsByContexts($has_context, $definitions
    * Provides data for testFilterPluginDefinitionsByContexts().
    */
   public function providerTestFilterPluginDefinitionsByContexts() {
-    $data = array();
-
-    $plugins = array();
-    // No context and no plugins, no plugins available.
-    $data[] = array(FALSE, $plugins, array());
-
-    $plugins = array('expected_plugin' => array());
-    // No context, all plugins available.
-    $data[] = array(FALSE, $plugins, $plugins);
-
-    $plugins = array('expected_plugin' => array('context' => array()));
-    // No context, all plugins available.
-    $data[] = array(FALSE, $plugins, $plugins);
-
-    $plugins = array('expected_plugin' => array('context' => array('context1' => new ContextDefinition('expected_data_type'))));
-    // Missing context, no plugins available.
-    $data[] = array(FALSE, $plugins, array());
-    // Satisfied context, all plugins available.
-    $data[] = array(TRUE, $plugins, $plugins);
-
-    $mismatched_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(array('mismatched_constraint_name' => 'mismatched_constraint_value'));
-    $plugins = array('expected_plugin' => array('context' => array('context1' => $mismatched_context_definition)));
-    // Mismatched constraints, no plugins available.
-    $data[] = array(TRUE, $plugins, array());
-
-    $optional_mismatched_context_definition = clone $mismatched_context_definition;
-    $optional_mismatched_context_definition->setRequired(FALSE);
-    $plugins = array('expected_plugin' => array('context' => array('context1' => $optional_mismatched_context_definition)));
-    // Optional mismatched constraint, all plugins available.
-    $data[] = array(FALSE, $plugins, $plugins);
-
-    $expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(array('expected_constraint_name' => 'expected_constraint_value'));
-    $plugins = array('expected_plugin' => array('context' => array('context1' => $expected_context_definition)));
-    // Satisfied context with constraint, all plugins available.
-    $data[] = array(TRUE, $plugins, $plugins);
-
-    $optional_expected_context_definition = clone $expected_context_definition;
-    $optional_expected_context_definition->setRequired(FALSE);
-    $plugins = array('expected_plugin' => array('context' => array('context1' => $optional_expected_context_definition)));
-    // Optional unsatisfied context, all plugins available.
-    $data[] = array(FALSE, $plugins, $plugins);
-
-    $unexpected_context_definition = (new ContextDefinition('unexpected_data_type'))->setConstraints(array('mismatched_constraint_name' => 'mismatched_constraint_value'));
-    $plugins = array(
-      'unexpected_plugin' => array('context' => array('context1' => $unexpected_context_definition)),
-      'expected_plugin' => array('context' => array('context2' => new ContextDefinition('expected_data_type'))),
-    );
-    // Context only satisfies one plugin.
-    $data[] = array(TRUE, $plugins, array('expected_plugin' => $plugins['expected_plugin']));
-
+    $data = [];
+
+    $user = new ContextDefinition('entity:user');
+    $node = new ContextDefinition('entity:node');
+    $page = new ContextDefinition('entity:node');
+    $page->addConstraint('Bundle', [0 => 'page']);
+    $article = new ContextDefinition('entity:node');
+    $article->addConstraint('Bundle', [0 => 'article']);
+    $multi_bundle = clone ($node);
+    $multi_bundle->addConstraint('Bundle', [0 => 'page', 1 => 'article']);
+    $plugins = [
+      'needs_node' => [
+        'context' => [
+          'node' => $node,
+        ],
+      ],
+      'needs_page' => [
+        'context' => [
+          'node' => $page,
+        ],
+      ],
+      'needs_article' => [
+        'context' => [
+          'node' => $article,
+        ],
+      ],
+      'needs_page_or_article' => [
+        'context' => [
+          'node' => $multi_bundle,
+        ],
+      ],
+      'needs_user' => [
+        'context' => [
+          'user' => $user,
+        ],
+      ],
+      'no_context_1' => [],
+      'no_context_2' => [],
+    ];
+    // No context, plugins without contextual requirements available.
+    $data[] = [[], $plugins, ['no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    // Node context, plugins without contextual requirements and node specific
+    // contexts available.
+    $data[] = [['node' => new Context($node)], $plugins, ['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    // Node of bundle page contexts, plugins without contextual requirements and
+    // node or page specific bundle contexts available.
+    $data[] = [['page' => new Context($page)], $plugins, ['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    // Node of bundle article contexts, plugins without contextual requirements
+    // and node or article specific bundle contexts available.
+    $data[] = [['article' => new Context($article)], $plugins, ['needs_node' => $plugins['needs_node'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    // Nodes of bundles page and article contexts, plugins without contextual
+    // requirements and node, page or article specific bundle contexts
+    // available.
+    $data[] = [['page' => new Context($page), 'article' => new Context($article)], $plugins, ['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    // User context, plugins without contextual requirements and user specific
+    // contexts available.
+    $data[] = [['user' => new Context($user)], $plugins, ['needs_user' => $plugins['needs_user'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
     return $data;
   }
 
